線程終止的方法
1、join(方法)
join()方法,其實是線程間通信的一種方法
如果在主線程中調用該方法,會讓主線程休眠,
讓調用該方法的線程執行完畢後再恢複執行主線程
從運作态到阻塞态 join(),會釋放對象鎖
阻塞态到就緒态 join()線程執行完畢
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+"、"+i);
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("main線程開始");
MyThread myThread=new MyThread();
new Thread(myThread,"子線程A").start();
System.out.println("main線程結束");
}
public static void PrintTime(){
Date date=new Date();
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str=dateFormat.format(date);
System.out.println(str);
}
}
運作結果:
在我們進行調用join()方法之前,我們發現,主線程,子線程,自己調用自己的線程
join方法隻是對于object提供的wait()做了一層封裝。
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
@Override
public void run() {
System.out.println("主線程休眠開始...." );
Test.PrintTime();
try {
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("主線程休眠結束....");
Test.PrintTime();
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
System.out.println("main線程開始");
MyThread myThread=new MyThread();
Thread thread= new Thread(myThread,"子線程A");
thread.start();
thread.join();
thread.sleep(2000);
System.out.println("main線程結束");
}
public static void PrintTime(){
Date date=new Date();
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str=dateFormat.format(date);
System.out.println(str);
}
}
運作結果:
我們可以發現,在執行join方法之後,我們的主線程開始停止運作,先執行我們的子線程。
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
這是實作join方法的一段源碼,我們可以可以看到join()方法的本質隻是一種對于wait方法的封裝。
線程停止的方法
1、設定标志位停止線程
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
private boolean flag=true;
@Override
public void run() {
int i=1;
while(flag){
System.out.println(Thread.currentThread().getName()+"第"+i+"次執行。。。");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
i++;
}
}
public void setFlag(boolean flag){
this.flag=flag;
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
MyThread mt=new MyThread();
Thread thread=new Thread(mt,"A");
thread.start();
thread.sleep(5000);
mt.setFlag(false);
}
}
運作結果:
- 我們可以看到,我們通過設定标志位,我們可以清晰地看見在我們主線程等待5秒的時間裡面,
- 我們的子線程每次運作隻等待1秒,是以的子線程在等待子線程的過程中,我們的子線程運作了5次。
- 5秒之後,由于我們的在主線程中将子線程設定的标志位改變,是以我們的子線程退出。
**
2、調用stop方法
**
調用stop方法強制停止線程,該方法不安全,已經被Deprecated
這種停止方式很同意産生我們的廢棄資料
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
private boolean flag=true;
@Override
public void run() {
int i=1;
while(flag){
System.out.println(Thread.currentThread().getName()+"第"+i+"次執行。。。");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
i++;
}
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
MyThread mt=new MyThread();
Thread thread=new Thread(mt,"A");
thread.start();
thread.sleep(5000);
thread.stop();
}
}
運作結果:
stop方法不安全在一旦調用它,它一旦執行,那我們調用它的線程會立馬退出,那麼很有可能産生垃圾資料。
3、調用Thread類的Interrupt()方法(能用不好了解)
interrupt()方法隻是将線程狀态置為中斷狀态而已,它不會中斷一個正在運作的線程。此方法隻是在給線程傳遞一個中斷的限号,程式可以根據此信号來判斷是否需要終止。是否要終止取決于程式中的處理。
這個标志位是系統幫助我們設定的
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyThread implements Runnable{
@Override
public void run() {
int i = 1;
while (true) {
boolean flag=Thread.currentThread().isInterrupted();
System.out.println(Thread.currentThread().getName() + "第" + i + "次執行。。。");
System.out.println(flag);
i++;
if(flag){
System.out.println("線程退出");
break;
}
}
}
}
public class Test {
public static void main(String[] args)throws InterruptedException {
MyThread mt=new MyThread();
Thread thread=new Thread(mt,"A");
thread.start();
thread.sleep(3000);
thread.interrupt();
}
}
當線程中使用wait 、sleep、join三個方法引起的阻塞,那麼會将線程的中斷标志重新設定false,并抛出一個InterruptedException;
并且将線程的中斷狀态由true置為false。
我們要知道,我們的interrupt隻是将我們的狀态改變,并不會将線程退出,如果要将線程退出,我們要做的就是将線上程中斷标志改變之後,所改變後的狀态要如何處理。