1、新建与运行
新建一个线程的从语法的角度上有两种:1、继承Thread重写run方法 2、实现Runnable接口重写run方法。之所以强调二者的区别在语法的角度是因为最终都是为了新建一个Thread对象,本质上都是调用Thread方法签名为Runnable构造方法。因为从多态的角度来说Thread类也实现了Runnable接口,二者都是Runnable的对象。
无论通过何种方式新建了一个Thread对象都要调用start方法才能以以多线程的方式去执行run,而调用run方法是傻乎乎的在当前线程下执行run方法。学术一点这是异步和同步的区别。异步和同步用来形容一次方法调用,如果调用一个方法必须等待方法执行结束才能进行后续操作,那么这次方法调用就是同步的。相应的如果方法调用后立即可以进行后续操作而不必等待调用的方法执行完成就称为异步的。显然start方法是异步的,因为start方法本质是把线程的运行状态从NEW不可逆的转变成RUNNABLE并把调度权限交给线程调度程序,具体什么时候执行是不可控的,而run方法是同步的,直接使用run方法也就失去的多线程的意义。
2、终止线程
这里所讨论的停止线程是在线程正常执行结束之前强制停止,这种强制的停止在单线程下似乎是没有问题的,在多线程的环境下解决线程安全问题会涉及到锁,线程停止会释放其所持有的锁,在一个原子操作执行结束前强行终止该原子操作并释放锁,这势必会带来不可预估的错误。
如下所示,写入线程在修改User对象的时候被强制终止并释放锁,读线程会读到一个未完全初始化的User对象。
正确合理的终止一个线程应该采用interrupt()方法。
package collection;public class UnsafeStop { private static User user = new User(); public static class writeThread extends Thread{ @Override public void run() { synchronized (user){ user.setAge(111); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } user.setWeight(111); } } } private static class readThread extends Thread{ @Override public void run() { synchronized (user){ System.out.println("Age is :"+user.getAge()); System.out.println("Weight is :"+user.getWeight()); } } } public static void main(String[] args) { Thread writeThread = new Thread(new writeThread()); Thread readThread = new Thread(new readThread()); writeThread.start(); writeThread.stop(); readThread.start(); }}
3、中断
线程中断是一种软性的停止线程的机制,他并不会立即终止线程否则就是stop,而是通知被中断线程“希望”该线程尽快停止,比如执行下述代码控制台会迅速的淹没在“你来中断我啊”的汪洋大海中。
public class testinterrupt extends Thread { @Override public void run() { while (true){ System.out.println("你来中断我啊"); Thread.yield(); } } public static void main(String[] args) { testinterrupt testinterrupt = new testinterrupt(); testinterrupt.start(); System.out.println("中断"); testinterrupt.interrupt(); }}
与interrupt线程的相关方法有三个:
- interrupt 实例方法,用于设置线程的中断标志位
- isinterrupted 实例方法,用于判断线程是否被中断
- interropted,静态方法,判断线程是否被中断并清除中断标志位
Thread.Interrupt方法只是设置相关线程的中断标志位,通知目标线程中断,即该方法只是修改标志位并没有对真正中断该线程。所以需要在目标类中手动添加中断处理逻辑,在发现了中断信号执行相关逻辑。
package collection;import java.util.TreeSet;public class testinterrupt extends Thread { @Override public void run() { while (true){ if(Thread.currentThread().isInterrupted()) { System.out.println("我被中断了"); break; } Thread.yield(); } } public static void main(String[] args) { testinterrupt testinterrupt = new testinterrupt(); testinterrupt.start(); System.out.println("中断"); testinterrupt.interrupt(); }}