使用interrupt来通知,而不是强制
java提供了interrrupt让一个线程来通知另一个线程停止
如果想中断一个线程,但是那个线程不想去中断,那就无能为力,我们没有强制去中断线程的手段,因为线程停止前需要做一定的收尾工作
所以正确停止线程,是如何用interrupt来通知那个线程,以及被停止的线程如何进行配合
代码展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class stopThreadWithoutSleep implements Runnable{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new stopThreadWithoutSleep()); thread.start(); Thread.sleep(1000); thread.interrupt(); } @Override public void run() { int num = 0; while(num <= Integer.MAX_VALUE / 2) { if (num % 10000 == 0) { System.out.println(num + "是10000的倍数"); } num++; } System.out.println("结束"); } } /* 由于太长,只展示结尾部分的结果 1073710000是10000的倍数 1073720000是10000的倍数 1073730000是10000的倍数 1073740000是10000的倍数 结束 * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class stopThreadWithoutSleep implements Runnable{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new stopThreadWithoutSleep()); thread.start(); Thread.sleep(1000); thread.interrupt(); } @Override public void run() { int num = 0; while(!Thread.currentThread().isInterrupted() && num <= Integer.MAX_VALUE / 2) { if (num % 10000 == 0) { System.out.println(num + "是10000的倍数"); } num++; } System.out.println("结束"); } } /* 由于太长,只展示结尾部分的结果 587830000是10000的倍数 587840000是10000的倍数 587850000是10000的倍数 587860000是10000的倍数 结束 * */ |
代码展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class stopThreadWithSleep { public static void main(String[] args) { Runnable runnable = () -> { int num = 0; while (num <= 300 && !Thread.currentThread().isInterrupted()) { if (num % 100 == 0) { System.out.println(num + "是100的倍数"); } num++; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }; Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } /* * 0是100的倍数 100是100的倍数 200是100的倍数 300是100的倍数 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.stopThreadWithSleep.lambda$main$0(stopThreadWithSleep.java:15) at java.lang.Thread.run(Thread.java:748) * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class stopThreadWithSleepEveryLoop { public static void main(String[] args) { Runnable runnable = () -> { int num = 0; try { while (num <= 10000) { if (num % 100 == 0) { System.out.println(num + "是100的倍数"); } num++; Thread.sleep(10); } } catch (InterruptedException e) { e.printStackTrace(); } }; Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(5000); } catch ( InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } /* * 0是100的倍数 100是100的倍数 200是100的倍数 300是100的倍数 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.stopThreadWithSleepEveryLoop.lambda$main$0(stopThreadWithSleepEveryLoop.java:15) at java.lang.Thread.run(Thread.java:748) Process finished with exit code 0 * * */ |
当catch写到while内,则不能正常中断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public class CantInterrupt { public static void main(String[] args) { Runnable runnable = () -> { int num = 0; while (num <= 10000) { if (num % 100 == 0) { System.out.println(num + "是100的倍数"); } num ++; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(5000); } catch ( InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } /* * 0是100的倍数 100是100的倍数 200是100的倍数 300是100的倍数 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.CantInterrupt.lambda$main$0(CantInterrupt.java:14) at java.lang.Thread.run(Thread.java:748) 400是100的倍数 500是100的倍数 600是100的倍数 700是100的倍数 800是100的倍数 900是100的倍数 Process finished with exit code -1 * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public class CantInterrupt { public static void main(String[] args) { Runnable runnable = () -> { int num = 0; while (num <= 10000 && !Thread.currentThread().isInterrupted()) { if (num % 100 == 0) { System.out.println(num + "是100的倍数"); } num++; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(5000); } catch ( InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } /* 0是100的倍数 100是100的倍数 200是100的倍数 300是100的倍数 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.CantInterrupt.lambda$main$0(CantInterrupt.java:14) at java.lang.Thread.run(Thread.java:748) 400是100的倍数 500是100的倍数 Process finished with exit code -1 * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class StopThreadInProd implements Runnable{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new StopThreadInProd()); thread.start(); Thread.sleep(1000); thread.interrupt(); } @Override public void run() { while (true) { System.out.println("start"); try { throwInMethod(); } catch (InterruptedException e) { System.out.println("保存日志/关闭程序"); e.printStackTrace(); } } } private void throwInMethod() throws InterruptedException { Thread.sleep(2000); } } /* * start 保存日志/关闭程序 start java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.StopThreadInProd.throwInMethod(StopThreadInProd.java:26) at com.jx.JavaTest.stopThread.StopThreadInProd.run(StopThreadInProd.java:17) at java.lang.Thread.run(Thread.java:748) start start Process finished with exit code -1 * * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class StopThreadInProd2 implements Runnable{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new StopThreadInProd2()); thread.start(); Thread.sleep(1000); thread.interrupt(); } @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("Interrupt"); break; } reInterrupt(); } } private void reInterrupt() { try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } } } /* java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.StopThreadInProd2.reInterrupt(StopThreadInProd2.java:25) at com.jx.JavaTest.stopThread.StopThreadInProd2.run(StopThreadInProd2.java:19) at java.lang.Thread.run(Thread.java:748) Interrupt * * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class StopThreadInProd2 implements Runnable{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new StopThreadInProd2()); thread.start(); Thread.sleep(1000); thread.interrupt(); } @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("Interrupt"); break; } reInterrupt(); } } private void reInterrupt() { try { Thread.sleep(2000); } catch (InterruptedException e) { // Thread.currentThread().interrupt(); e.printStackTrace(); } } } /* java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.jx.JavaTest.stopThread.StopThreadInProd2.reInterrupt(StopThreadInProd2.java:25) at com.jx.JavaTest.stopThread.StopThreadInProd2.run(StopThreadInProd2.java:19) at java.lang.Thread.run(Thread.java:748) * * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
public class StopThread implements Runnable{ @Override public void run() { // 模拟指挥军队,一共五个连队,每个连队一百人 // 以连队为单位发放武器 for (int i = 0; i < 5; i++) { System.out.println("连队" + i + "领取武器"); for (int j = 0; j < 10; j++) { System.out.println(j); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("连队" + i + "领取完毕"); } } public static void main(String[] args) { Thread thread = new Thread(new StopThread()); thread.start(); try { thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread.stop(); } } /* * 连队0领取武器 0 1 2 3 4 5 6 7 8 9 连队0领取完毕 连队1领取武器 0 1 2 3 4 5
Process finished with exit code 0
* */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class Volatile implements Runnable { private volatile boolean canceled = false; @Override public void run() { int num = 0; try { while (num <= 10000 && !canceled) { if (num % 100 == 0) { System.out.println(num + " 是100的倍数"); } num++; Thread.sleep(1); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { Volatile v = new Volatile(); Thread thread = new Thread(v); thread.start(); Thread.sleep(1000); v.canceled = true; } } /* *0 是100的倍数 100 是100的倍数 200 是100的倍数 300 是100的倍数 400 是100的倍数 500 是100的倍数 600 是100的倍数 Process finished with exit code 0 * * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
// 模拟生产者和消费者 public class cantStop { public static void main(String[] args) throws InterruptedException { // 阻塞队列 // 满了之后,放不进去 // 空的时候取数据,也会堵塞 ArrayBlockingQueue storage = new ArrayBlockingQueue(10); Producer producer = new Producer(storage); Thread producerThread = new Thread(producer); producerThread.start(); Thread.sleep(1000); Consumer consumer = new Consumer(storage); while (consumer.needMore()) { System.out.println(consumer.storage.take() + "被消费"); Thread.sleep(100); } System.out.println("消费者不需要更多数据"); // 消费者不需要数据,让生产者停下来 producer.canceled = true; } } // 生产者 class Producer implements Runnable { public volatile boolean canceled = false; BlockingQueue storage; public Producer(BlockingQueue storage) { this.storage = storage; } @Override public void run() { int num = 0; try { while (num <= 10000 && !canceled) { if (num % 100 == 0) { // 当堵塞队列满了之后,会堵塞在这里,而这段代码没有判断机制 storage.put(num); System.out.println("num" + "生产"); } num++; } } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("生产者停止运行"); } } } // 消费者 class Consumer { BlockingQueue storage; public Consumer(BlockingQueue storage) { this.storage = storage; } public boolean needMore() { if (Math.random() > 0.9) { return false; } return true; } } /* * num生产 num生产 num生产 num生产 num生产 num生产 num生产 num生产 num生产 num生产 0被消费 num生产 消费者不需要更多数据
* * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
public class finxed { public static void main(String[] args) throws InterruptedException { finxed finxed = new finxed(); // 阻塞队列 // 满了之后,放不进去 // 空的时候取数据,也会堵塞 ArrayBlockingQueue storage = new ArrayBlockingQueue(10); Producer producer = finxed.new Producer(storage); Thread producerThread = new Thread(producer); producerThread.start(); Thread.sleep(1000); Consumer consumer = finxed.new Consumer(storage); while (consumer.needMore()) { System.out.println(consumer.storage.take() + "被消费"); Thread.sleep(100); } System.out.println("消费者不需要更多数据"); // 消费者不需要数据,让生产者停下来 producerThread.interrupt(); } class Producer implements Runnable { public volatile boolean canceled = false; BlockingQueue storage; public Producer(BlockingQueue storage) { this.storage = storage; } @Override public void run() { int num = 0; try { while (num <= 10000 && !Thread.currentThread().isInterrupted()) { if (num % 100 == 0) { storage.put(num); System.out.println("num" + "生产"); } num++; } } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("生产者停止运行"); } } } class Consumer { BlockingQueue storage; public Consumer(BlockingQueue storage) { this.storage = storage; } public boolean needMore() { if (Math.random() > 0.9) { return false; } return true; } } } /* * 2100被消费 num生产 2200被消费 num生产 2300被消费 num生产 消费者不需要更多数据 生产者停止运行 java.lang.InterruptedException at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2014) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2048) at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:353) at com.jx.JavaTest.stopThread.volatiledmo.finxed$Producer.run(finxed.java:51) at java.lang.Thread.run(Thread.java:748) Process finished with exit code 0 * * */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(this); return; } } interrupt0(); } private native void interrupt0(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class InterruptedTest { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { while (true) {
} } }); thread.start(); thread.interrupt(); // 获取中断标志 System.out.println(thread.isInterrupted()); // true // 获取中断标志并重置 System.out.println(thread.interrupted()); //false System.out.println(Thread.interrupted()); // false System.out.println(thread.isInterrupted()); //true thread.join(); System.out.println("over"); } } |