💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## 开启线程的三种方式 ~~~ //第一种是Thread开启 Thread t = new Thread(){ public void run(){ } }.start(); //Runnable开启 Runnbale r = new Runnbale(){ public void run(){ } } new Thread(r).start(); //Callable作为内部类,返回Future。这里简单说一下,Runnable与Future的区别 //1、Runnable无返回值,而Future有 //2、Runnable无法抛异常,而Future可以 Callable c = new Callable(){ public String call() throws Exception{ return "s"; } } ExecutorService mExecuterService = Executor.newSingleThreadPool(); Future future = mExecuterService.submit(c) Future future ~~~ ## 生命周期 ![](https://img.kancloud.cn/97/d5/97d50bd1d62a1f6b56a936f10b606602_1220x816.png) ## 中断interrupt ### interrupt() 线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序本身。 ### isInterrupted() 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。 ### 写法 ~~~ public void run() { try { ... /* * 不管循环里是否调用过线程阻塞的方法如sleep、join、wait,这里还是需要加上 * !Thread.currentThread().isInterrupted()条件,虽然抛出异常后退出了循环,显 * 得用阻塞的情况下是多余的,但如果调用了阻塞方法但没有阻塞时,这样会更安全、更及时。 */ while (!Thread.currentThread().isInterrupted()&& more work to do) { do more work } } catch (InterruptedException e) { //线程在wait或sleep期间被中断了 Thread.currentThread().interrupt();//重新设置中断标示 } finally { //线程结束前做一些清理工作 } } ~~~ 其实,Java的中断是一种协作机制。也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己。每个线程都有一个boolean的中断状态(这个状态不在Thread的属性上),interrupt方法仅仅只是将该状态置为true。 比如对正常运行的线程调用interrupt()并不能终止他,只是改变了interrupt标示符。 一般说来,如果一个方法声明抛出InterruptedException,表示该方法是可中断的,比如wait,sleep,join,也就是说可中断方法会对interrupt调用做出响应(例如sleep响应interrupt的操作包括清除中断状态,抛出InterruptedException),异常都是由可中断方法自己抛出来的,并不是直接由interrupt方法直接引起的。 **Object.wait, Thread.sleep方法,会不断的轮询监听 interrupted 标志位,发现其设置为true后,会停止阻塞并抛出 InterruptedException异常。** ## join()  join()方法会使当前线程等待调用join()方法的线程结束后才能继续执行 join的作用就是将线程串行化,需要注意的是,join()一定要放在现场开启(start())后。 ## wait sleep join ### sleep()  sleep()方法需要指定等待的时间,它可以让当前正在执行的线程在指定的时间内暂停执行,进入阻塞状态 ### wait()  wait()方法需要和notify()及notifyAll()两个方法一起介绍,这三个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块内使用,也就是说,调用wait(),notify()和notifyAll()的任务在调用这些方法前必须拥有对象的锁。 ### wait和sleep的区别 1. wait只能在同步(synchronize)环境中被调用,而sleep不需要。 2. 进入wait状态的线程能够被notify和notifyAll线程唤醒,但是进入sleeping状态的线程不能被notify方法唤醒。 3. wait通常有条件地执行,线程会一直处于wait状态,直到某个条件变为真。但是sleep仅仅让你的线程进入睡眠状态。 4. wait方法在进入wait状态的时候会释放对象的锁,但是sleep方法不会。 5. wait方法是针对一个被同步代码块加锁的对象,而sleep是针对一个线程。更详细的讲解可以参考《Java核心技术卷1》,里面介绍了如何使用wait和notify方法。