1.线程创建的几种方式?
- extends Thread类,重写run()方法
- implements Runnable接口,重写run()方法
- 利用线程池:Excutors
//固定数量的线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
//单任务线程池
ExecutorService pool = Executors.newSingleThreadExecutor();
//可变线程池
ExecutorService pool = Executors.newCachedThreadPool();
//定时线程池
ScheduledExecutorService pool= Executors.newScheduledThreadPool(2);
- 利用ExecutorService、Callable、Future 实现有返回结果的多线程
/**
* @program: demo
* @description: ${description}
* @author: Will Wu
* @create: 2018-12-06 20:00
**/
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
public class MyCallable implements Callable <Object>{
private String taskNum;
@Override
public Object call() throws Exception {
log.info("=======>"+taskNum+" 任务启动...");
Date date1 = new Date();
Thread.sleep(1000);
Date date2= new Date();
long time=date2.getTime()-date1.getTime();
log.info("=======>"+taskNum+" 任务结束...");
return taskNum+"任务返回运行结果,当前任务时间耗时:" + time+"毫秒";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
log.info("程序开始运行...");
Date date = new Date();
int size=5;
ExecutorService pool = Executors.newFixedThreadPool(size);
ArrayList<Future> list = new ArrayList<>();
for(int i=0;i<size;i++){
MyCallable callable = new MyCallable(i + "");
Future<Object> future = pool.submit(callable);
log.info(future.get().toString());
list.add(future);
}
pool.shutdown();
list.stream().collect(Collectors.toList()).forEach(System.out::println);
}
}
2.wait()和sleep()方法的区别
-
最大的区别在于sleep方法并没有释放锁,wait方法释放了锁;
-
所以sleep方法一般用于暂停执行的场景,wait则通常用于线程加交互;
3.synchronized 和 volatile 关键字的作用
- 就我个人理解而言,synchronized关键字主要是锁定当前变量,只允许当前线程访问该变量,其他变量处于阻塞状态;而volatile关键字,保证了不同线程对该变量进行操作的可见性,即一个线程修改了某变量,修改后的新值对于其他线程来说是立即可见的
- synchronized关键字可以用在代码块,方法和变量上,volatile关键字只能用于变量上
4. java内存模型中线程运行机制
在java内存模型中,每一个线程运行时都有一个线程栈,线程栈保存了线程运行时变量的相关信息,当线程访问某个对象的时候,首先通过对象的引用找到对应堆内存的变量的值,然后把堆内存里该变量的具体值加载到线程本地内存,建立一个变量副本,之后线程就不在跟对象的堆内存变量值有任何联系,而是直接修改副本变量的值,修改完之后,自动把线程变量副本的值同步到堆内存中该变量的值,从而该变量的值发生了变化
5.如何控制某个方法允许并发访问线程的个数?
/**
* @program: demo
* 如何控制某个方法允许并发访问线程的个数
* @description: ${description}
* @author: Will Wu
* @create: 2018-12-08 10:06
**/
public class SeamphoreTest {
//采用该Semaphore类,如下代码去控制test()方法最多五个线程并发访问
static Semaphore semaphore=new Semaphore(5,true);
public static void main(String[] args) {
for(int i=0;i<100;i++){
new Thread(new Runnable() {
@Override
public void run() {
test();
}
}).start();
}
}
public static void test(){
try {
//申请一个请求
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"is coming...");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"is going...");
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();
}
}