1.首先我们来了解java中的一个join()方法,它是Thread中的一个方法,join()方法在java的API文档时的描述为:

浅谈java多线程(二)——线程的中断

 join()方法 在主线程中,加入了myThread.join();  把谁加入了就要等谁。同时join还有join(millis)方法,可以加入等待时间,效果上类似sleep,但是还是有实际区别的。join底层是wait方法,所以它是会释放对象锁的,而sleep在同步的方法中是不释放对象锁的,只有同步方法执行完毕,其他线程才可以执行。当main线程调用到Thread-0的时候,这个时候main线程是等待状态,直到join守护完毕才执行下面的东西。join方法是先将线程池中的其它线程wait状态,join执行完毕,又调用了notifyAll()唤醒所有线程中的线程。下面画个图简单模拟一下过程:

浅谈java多线程(二)——线程的中断

下面我们通过代码简单的测试一下join方法代码如下:

public class Domajoin {

	public static void main(String[] args) {
		
		Damo1 dom=new Damo1();
		Thread t1=new Thread(dom);
		
		t1.start();
		
		
		for (int i = 0; i <50; i++) {
			
			
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		
			if(i==20){
				try {
					t1.join();
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				} 	
			}
			System.out.println("main="+i);
		}
		
        
	}

}

class Damo1 implements Runnable{
	public void run() {
		for (int i = 0; i <50; i++) {
			
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
		
			System.out.println(Thread.currentThread().getName()+i);		
			
			
		}
		
	}
}

我们在mian这个线程加入Dom1a这个线程类的join方法,我们发现刚开始时两线程交替打印在mian这个线程的i打印到20时,便停止打印此时只有Doma1这个线程的i再继续打印,当它打印完以后mian中的i才开始继续打印。

2.我们来讲讲线程的中断。

我们知道线程一启动后就是不可控的,除非线程中断自身第一种方式,我们通过interrupt()方法来实现,interrupt只是起到一个中断标记的作用,然后我们通过Thread类里面的public static boolean interrupted()来测试这个线程是否中断,该方法可以清除线程的中断转态,该方法被连续调用两次第二个调用将返回false(除非当前线程再次中断,在第一个调用已经清除中断状态之后,在第二个调用之前已经检查过)下面我们通过代码测试怎么使用interrupt()中断标记来实现线程的中断:

public class Damointerrupt {

	
	public static void main(String[] args) {
		Damon1 dd=new Damon1();
		Thread t1=new Thread(dd);
		t1.start();
	  for (int i = 0; i < 50; i++) {
		  
		  
		  try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		}
		  
		  System.out.println("main="+i);
		  if(i==20){
			  
			  t1.interrupt();//中断线程,只是一个中断标记
		  }
		
	}
	  

	}

}
class Damon1 implements Runnable{
	
	public void run() {
		
		
		for (int i = 0; i <50; i++) {
			if(Thread.interrupted()){//测试中断状态,并且会把中断状态清除
				break;
			}
			
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
				Thread.currentThread().interrupt();//重新打回中断状态
			}
			
			System.out.println(Thread.currentThread().getName()+"="+i);
		}
		
	}
}
	

这样Damo线程会在i打印到20时中断:

2.我们发现这样的方法比较麻烦,我们在中断线程时一般采用中断线程的另外一种方式:自定义标记法:

代码如下:

public class Damoboolean {

	
	public static void main(String[] args) {
		
		Damo2 dd=new Damo2();
		Thread t1=new Thread(dd);
		t1.start();
		for (int i = 0; i <50; i++) {
			System.out.println("main="+i);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			if(i==20){
				
				dd.flag=false;//当布尔值改为false时线程中断
			}
			
		}
		

	}

}
class Damo2 implements Runnable{
	public boolean flag=true;
	
	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public void run() {
		int i=0;
		while(flag){
		
				System.out.println(Thread.currentThread().getName()+"="+i++);
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			
			
		}
		
		
	}
	
}

我们发现这种自定义标记的方式很容易实现线程的中断,笔者推荐使用这种方法

相关文章: