持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情
volatile 使用
使用volatile方式如下:
public static volatile boolean isStop;
public static void main(String[] args) throws Exception{
new Thread(()->{
while(!isStop){
//业务逻辑
}
}).start();
Thread.sleep(1000);
isStop = true;
}
通过volatile关键字保证了isStop变量的可见性,当主线程设置isStop为true时,子线程将会读取到最新值,从而停止线程。
Synchronized关键字使用
synchronized关键字同步方式是通过锁实现。
Synchronized关键字可以修饰静态方法、修饰实例方法、修饰代码块,代码实现如下所示。
public class SynchornizedRun {
public synchronized static void m1(){
System.out.println("静态方法");
}
public synchronized void m2(){
System.out.println("实例方法");
}
public void m3(){
synchronized (this){
System.out.println("代码块");
}
}
}
注意点:
synchornized关键字在静态方法中的使用相当于对class对象上锁,而在方法或者方法内均是对类的对象实例上锁。
Executor接口原理
Executor接口是线程池的最顶层接口,它的源码如下:
public interface Executor{
void execute(Runnable command);
}
参数只需要传入一个Runnable,然后任务即可被执行。设计层面上设计为单线程执行,即command.run(),也就是每个Runnable对象启动一个线程来执行,即new Thread(command).start()。Executor其实是一个执行器,抽象地一个Runnable任务如何执行。
如果采用开启线程执行command,那么会发生什么问题呢?JVM创建一个线程是非常昂贵的,而且还需要陷入内核上下文切换,如此创建一个线程仅仅是为了执行一个command,未免太过浪费,如果有n个command,基于new Thread(command).start()方式,就会启动n个线程,那么怎样优化它们?
将线程Thread缓存起来,如缓存10个线程来处理这n个任务,但是当n大于10时,可以通过创建队列来保存多余的任务即可。关于这两点问题,所以为什么要用到线程池了,而线程池大概就是一个是保存任务的队列,一个保存线程对象的结构。