多线程二 基本技能 (2)

查看FutrueTask的源码,我们可以看到,call()是由FetureTask的run()执行的,

public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true;

run()方法&call()方法

Runable的Run方法 是由 线程异步调用的

虽然是耗时的操作,如果可能出现阻塞,由新的线程中执行,会节省时间

Callable的 call 方法,同步调用的,是由Future的run方法调用的,而这个run方法,是对Runable接口里面run()的重写

依然是耗时的操作

在往线程池中提交任务时 submit()方法同样可接受Callable对象,后续会详解

Future<String> future = threadPoolExecutor.submit(new Callable<String>() { @Override public String call(){ ai.getAndIncrement(); return Thread.currentThread().getName(); } }); 四. Thread常用API 1 . interrupt() & isInterrupted()

interrupted():

作用: 中断当前线程,但是! 相比于废弃的stop() 并不是真正意义上的中断,而是打上了一个标记, 表示想要中断它.但是呢?在中断它之前要让他把该做的事,该跑的代码 跑完!

特性:

第一次执行interrupt()----> 标记当前线程是要被中断的

第二次执行interrupt()----> 清除所有标记

它要配合 isInterrupted() ,作为条件,判断当前的状态,去中断, 本函数多次调用不会 改变 当前线程的状态

实例代码

停不下来的线程 /* * 停止不了的线程 * */ public class CanNotStop extends Thread{ AtomicInteger value = new AtomicInteger(1); @Override public void run() { value.getAndIncrement(); System.out.println("当前的value== "+value); /* * isInterrupted() 方法, 判断当前线程的状态去中断线程, * 假如说,当前线程被标记为要去中断, 被isInterrupted()限制的Target方法不再执行,条件之外的代码,能且只能执行一次! 然后彻底被中断 * */ while(!isInterrupted()) { try { sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } try { sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "执行了.."); } System.out.println("你真的以为我被中断了吗?"); } public static void main(String[] args) { //初始化 CanNotStop canNotStop = new CanNotStop(); CanNotStop canNotStop2 = new CanNotStop(); canNotStop.start(); canNotStop2.start(); /* * 关于interrupt()方法,这个方法 * 作用: * 中断当前线程,但是! 相比于废弃的stop() 并不是真正意义上的中断,而是打上了一个标记, 表示想要中断它.但是呢?在中断它之前要让他把该做的事, * 该跑的代码 跑完! * 特性: * 第一次执行interrupt()----> 标记当前线程是要被中断的 * 第二次执行interrupt()----> 清除所有标记 * * 它要配合 isInterrupted() ,作为条件,判断当前的状态,去中断, 本函数多次调用不会 改变 当前线程的状态 * */ canNotStop.interrupt(); try { sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //被中断就相当于死掉了? synchronized (canNotStop){ canNotStop.notifyAll(); } } }

这也称作是停止不了的线程,为啥这样说呢? 可以看到,执行 canNotStop.interrupt();代码的是谁? 没错主线程!细想一下,执行这个语句时,新创建的线程,本来就没有抢到CPU的执行权,也就是说他本来就是停止的... 他的原理就是打个标记,等到被打上标记的线程抢到CPU的执行权的时候,去判断一下就行了,如果存在被中断的标记,就什么事都不做,反之则执行任务.其实,它还活着

2 currentThread()

返回当前代码,正在被哪个线程调用

3 isAlive()

判断当前线程是否处于存活状态,线程处于正在运行或者等待运行的状态返回true,线程运行完毕返回false

4 sleep()

指定在线程休眠的时间,在指定的时间后,重新进入就绪状态去竞争CPU的执行权

5 getId() & getName()

返回线程的id & 名字

6 停止线程

异常停止

throw new InterruptedException();

在睡眠中停止

先被打上停止的标记interrupt(),再遇到sleep(),程序直接进入catch块

先睡眠sleep(),再被打上Interrupt(),程序进入catch块,并且清除停止状态值,使之变成false;

暴力停止

stop(),线程立即停止,不再执行后续的代码,已被废弃

return停止线程

@Override public void run(){ while(true){ if(this.isInterrupted()){ return; } System.out.println("if 后面的代码"); } }

推荐使用的是剖出异常的停止线程的方法,因为有了异常之后,可以在catch块中对异常进行处理,让程序更加流畅

7 yield()

让当前的线程放弃对cpu的使用权,但是也可能会发生,刚放弃就重新获取到了执行权的情况

不会释放锁

8 暂停线程

suspend() 暂停线程被废弃

resume() 配合suspend()唤醒线程被废弃

五. 线程的优先级

线程的优先级用处是,把任务的重要性告诉调度器,让任务的调度器,更倾向于优先级高的线程先执行,但是也存在优先级底的线程先执行的可能

在<>提到,在绝大多数情况下,都应该使线程按照默认的优先级规则执行,试图操作优先级让线程先执行,通常是一种错误

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsgpj.html