JUC之线程的启动和中止
一、线程的实现
1、继承Thread类
public class ThreadDemo extends Thread { @Override public void run() { System.out.println("1111"); } public static void main(String[] args) { Thread thread = new ThreadDemo(); thread.start(); } }
2、实现Runnable接口
public class RunnableDemo implements Runnable { @Override public void run() { System.out.println("线程名->" + Thread.currentThread().getName()); } public static void main(String[] args) { Thread thread = new Thread(new RunnableDemo()); thread.start(); } }
3、实现Callable接口
/* ==============实现Callable<Object>接口================ * 1.线程有返回值 * 2.可通过Future接口的实现类保存call()方法的返回值 * 3.Callable<String>中的String是call()方法的返回值类型 * 4.FutureTask是Runnable的子类型 */ public class CallableDemo implements Callable<String> { @Override public String call() throws Exception { return "线程名->" + Thread.currentThread().getName(); } public static void main(String[] args) { CallableDemo callableDemo = new CallableDemo(); FutureTask<String> futureTask = new FutureTask<String>(callableDemo); Thread thread = new Thread(futureTask); thread.start(); System.out.println("主线程:" + Thread.currentThread().getName()); try { String object = futureTask.get(); System.out.println(object); } catch (Exception e) { e.printStackTrace(); } } }
4.总结:
A、第一种方法和第二种方式基本相同,但是推荐使用实现Runnable接口的方式,根据面向接口编程的思想,接口扩展性更强,而类只能被单继承,扩展性差, 如果需要需要集成其他类就无法实现。
B、 如果使用场景中,线程需要返回执行结果或者需要返回执行结果,则使用用Callable的方式。
二、线程的中止
1、stop()方法
stop()方法是java.lang.Thread提供的停止线程的方法,目标前JDK已经标记为过时,不推荐使用,就不在写demo介绍。
过时原因:
(1) stop()可以停止一个正在运行的线程,同时,终止线程的run()方法中正在执行的任务,包括catch
或finally语句中的,并抛出ThreadDeath异常,操作共享资源,就会导致共享资源不完整,造成数据不安全问题。
(2) stop()方法在执行时会释放所持有的所有锁,也会对程序执行造成影响,造成数据不一致的影响。
2、interrupt()方法
interrupt()方法执行后并不会终止线程执行,而是改变isInterrupted()的状态,线程内部通过感知isInterrupted()的状态
决定线程的终止时间,也就是说如果没有上文中的if判断,线程会一直执行下,并不会终止。
public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { while (true) { if(Thread.currentThread().isInterrupted()) { break; } System.out.println("测试"); } }, "线程A"); thread.start(); System.out.println("线程中断状态:\t" + thread.isInterrupted()); TimeUnit.MILLISECONDS.sleep(100); thread.interrupt(); System.out.println("线程中断状态:\t" + thread.isInterrupted()); }
3、 标志位中止线程
使用标志位的方式和interrupt()方法相似,在线程外定义一个线程可见的标志,通过线程感知标志的状态来终止线程。
public class DmConnectionTest implements Runnable{ //为保证变量可见性,用volatile修饰 private volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { DmConnectionTest dmConnectionTest = new DmConnectionTest(); Thread thread = new Thread(dmConnectionTest); thread.start(); System.out.println("线程中断状态:\t" + dmConnectionTest.flag); TimeUnit.MILLISECONDS.sleep(100); dmConnectionTest.flag = false; System.out.println("线程中断状态:\t" + dmConnectionTest.flag); } @Override public void run() { while (flag) { System.out.println("测试"); } System.out.println("线程执行结束"); } }
总结: A.stop()由于会造成数据安全性问题,现在已经不再使用
B.使用标志位方法更简单,但是如果线程是阻塞的,则不能使用,所以推荐JDK自带的方法interrupt();