1.2JAVA高性能编程专题-认识多线程

线程状态

在java.lang.Thread.State定交了6个状态:

  • New:尚未启动的线程的线程状态。
  • Runnable:可运行线程的线程状态,等待CPU调度。
  • Blocked:线程阻塞等待监视器锁定的线程态。处于synchronized同步代码块或方法中被阻塞。
  • Waiting:等待线程的线程状态。下列不带超时的方式:Object.wait、Thread.join、LockSupport.park
  • Timed Waiting:具有指定等待时间的等待线程的线程状态。下列带超时的方法thread.sleep、Object.wait(long timeout)、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil
  • Terminated:终止线程的线程状态。线程正常完成执行或者出现异常。

以下是线程状态切换图:

接着上一段代码,演示一下各种状态的切换效果:

public class Demo2 {
	//public static Thread thread1;
	public static void main(String[] args) throws InterruptedException {
		System.out.println("第一种:新建 -> 运行 -> 终止");
		Thread thread1 = new Thread(new Runnable() {
			
			public void run() {
				System.out.println("thread1状态:"+Thread.currentThread().getState().toString());
				System.out.println("thread1执行了");
			}
		});
		
		System.out.println("start方法前:"+thread1.getState().toString());
		thread1.start();
		thread1.sleep(2000L);
		System.out.println("start方法后:"+thread1.getState().toString());
//		thread1.start(); TODO 注意:线程终止后,再运行调用start(),会抛出IllegalThreadStateException异常
		
		System.out.println("第二种:新建 -> 运行 -> 等待 -> 运行-> 终止");
		Thread thread2 = new Thread(new Runnable() {
			
			public void run() {
				try {
					Thread.sleep(1500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("thread2状态:"+Thread.currentThread().getState().toString());
				System.out.println("thread2执行了");
			}
		});
		
		System.out.println("thread2 start方法前:"+thread2.getState().toString());
		thread2.start();
		System.out.println("thread2 start方法后:"+thread2.getState().toString());
		thread2.sleep(200L);
		System.out.println("thread2  等待200毫秒后:"+thread2.getState().toString());
		thread2.sleep(3000L);
		System.out.println("thread2  等待3秒后:"+thread2.getState().toString());
	
		System.out.println("第三种:新建 -> 运行 -> 堵塞 -> 运行-> 终止");
		Thread thread3 = new Thread(new Runnable() {

			public void run() {
				synchronized(Demo2.class) {
					System.out.println("thread3 状态:"+Thread.currentThread().getState().toString());
					System.out.println("thread3 执行了");
				}
			}
		});
		
		synchronized (Demo2.class) {
			System.out.println("thread3 start前:"+ thread3.getState().toString());
			thread3.start();
			System.out.println("thread3 start后:"+ thread3.getState().toString());
			Thread.sleep(200);
			System.out.println("thread3  等待200毫秒后:"+thread3.getState().toString());
		}
		Thread.sleep(3000);
		System.out.println("thread3  等待3秒后:"+thread3.getState().toString());
		
	}
}

运行结果如下:

第一种:新建 -> 运行 -> 终止
start方法前:NEW
thread1状态:RUNNABLE
thread1执行了
start方法后:TERMINATED
第二种:新建 -> 运行 -> 等待 -> 运行-> 终止
thread2 start方法前:NEW
thread2 start方法后:RUNNABLE
thread2  等待200毫秒后:TIMED_WAITING
thread2状态:RUNNABLE
thread2执行了
thread2  等待3秒后:TERMINATED
第三种:新建 -> 运行 -> 堵塞 -> 运行-> 终止
thread3 start前:NEW
thread3 start后:RUNNABLE
thread3  等待200毫秒后:BLOCKED
thread3 状态:RUNNABLE
thread3 执行了
thread3  等待3秒后:TERMINATED
 

其中:synchronized(Demo2.class),表示去拿主线程的一把锁。如果该锁已经被其他代码争抢了,则在去取这把锁的时候将进入阻塞状态。直到这把锁被释放后,争抢成功才会进入下步的执行动作。

 

线程中止

不正确的线程中止-Stop

Stop:中止线程,并且清除监控器锁的信息,但是可能导致线程安全问题,JDK不建议用。

Destory:JDK未实现该方法。

以下有两段代码:

StopThread.java

public class StopThread extends Thread{
	private int i=0,j=0;
	
	@Override
	public void run() {
		synchronized (this) {
			++i;
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			++j;
		}
	}
	
	public void print() {
		System.out.println("i="+i+",j="+j);
	}
}

Demo3.java

public class Demo3 {
	public static void main(String[] args) throws InterruptedException {
		StopThread thread=new StopThread();
		thread.start();
		Thread.sleep(1000);
		thread.stop();
		while(thread.isAlive()) {
			//保证线程已经中止
		}
		thread.print();
	}
}

其中synchronized (this)代码块的用意是保证synchronized块内代码执行代码的线程安全,不受其它线程影响。

但stop,强行中止了线程。造成结果是:

i=1,j=0
 

正确的线程中止- interrupt

如果目标线程在调用Object class的wait()、wait(long)或wait(long,int)方法、join()、join(long,int)或sleep(long,int),方法时被阻塞,那么Interrupt会生效,该线程的中断状态将被清除,抛出InterruptedException异常。

如果目标线程是被I/O或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。

如果以上条件都不满足,则会设置此线程的中断状态。

如果将刚才Demo3中的stop改为interrupt

运行结果如下:

我们可以看到,运行的结果除了i=1,j=1

使用interrupt去中上线程,java会以一种异常的方式通知开发人员,由开发人员去处理这个异常。从而保证了线程安全。

正确的线程中止- 标志位

代码逻辑中,增加一个判断,用来控制线程的中止。

public class Demo4 extends Thread{
	public volatile static boolean flag=true;
	public static void main(String[] args) throws InterruptedException {
		new Thread(() -> {
			try {
				while(flag) {
					System.out.println("运行中");
					Thread.sleep(1000);
				}
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}).start();
		
		Thread.sleep(3000);
		flag=false;
		System.out.println("程序运行结束");
	}
}

执行结果如下:

运行中
运行中
运行中
程序运行结束

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页