Java多线程
1. synchronized同步锁
2. concurrent--并发工具包
//以下类都线程安全
ConcurrentHashMap
LinkedBlockingQueue --线程安全的阻塞(继承BlockingQueue)队列,可以指定容量,也可以不指定,不指定则默认值最大Integer.MAX_VALUE,其中主要用到put和take方法 ,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。
ConcurrentLinkedQueue -- 非阻塞队列,当queue为空时不阻塞,而是返回null,需要程序自己进行处理
3. Excutor-线程池-优先-Runnable
3.0 自定义线程池中线程名称
执行run方法前设置线程的名称,这样jstack0看到的线程名就可以是自定义的
3.0 实现类-实现Runnable的run方法
public class LiftOff implements Runnable {
private int index ;
LiftOff(int xx) {
this.index = xx;
}
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("current thread: "+Thread.currentThread().getId()+ ",index:"+this.index);
}
}
3.1 Excutor.newCatchedThreadPool-每次创建线程,少用
为每个任务都创建一个线程。当前的main线程继续运行,在Executor中的所有任务完成之后尽快退出。
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
exec.execute(new LiftOff(i));
}
//shutdown()方法的调用可以防止新任务被提交给Executor。
exec.shutdown();
System.out.println("main finished!");
//可看出结果是无序的
main finished!
main finished!
current thread: 11,index:0
current thread: 12,index:1
current thread: 13,index:2
current thread: 15,index:4
current thread: 14,index:3
current thread: 16,index:5
current thread: 17,index:6
current thread: 20,index:9
current thread: 19,index:8
current thread: 18,index:7
3.2 Excutor.newFixedThreadPool-数量固定,线程池,复用-常用
预先执行一次代价昂贵的线程分配,复用线程来执行所提交的任务
ExecutorService exec = Executors.newFixedThreadPool(2);
for (int i = 0; i < 3; i++) {
exec.execute(new LiftOff(i));
}
//shutdown()方法的调用可以防止新任务被提交给Executor。
exec.shutdown();
System.out.println("main finished!");
//可看出只使用了两个线程执行任务
main finished!
current thread: 12,index:1
current thread: 11,index:0
current thread: 11,index:3
current thread: 12,index:2
current thread: 11,index:4
current thread: 12,index:5
current thread: 11,index:6
current thread: 12,index:7
current thread: 11,index:8
current thread: 12,index:9
3.3 Executor.newSingleThreadExecutor-单线程按序执行
数量1的newFixedThreadPool,多个任务排队执行.如多个线程都需要使用文件系统,可免去同步的操作
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
exec.execute(new LiftOff(i));
}
//shutdown()方法的调用可以防止新任务被提交给Executor。
exec.shutdown();
System.out.println("main finished!");
//可看出是按序执行
main finished!
current thread: 11,index:0
current thread: 11,index:1
current thread: 11,index:2
current thread: 11,index:3
current thread: 11,index:4
3.4 Executor.newScheduledThreadPool 定时任务-线程池
public class LiftOff implements Runnable {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Current thread:"+Thread.currentThread().getId()+", CurrentTime:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E").format(new Date()));
}
}
ScheduledExecutorService exec = Executors.newScheduledThreadPool(2);
for (int i = 0; i < 5; i++) {
//exec.execute(new LiftOff(i));
exec.schedule(new LiftOff(i),3, TimeUnit.SECONDS);
}
//shutdown()方法的调用可以防止新任务被提交给Executor。
exec.shutdown();
System.out.println("Current Time:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E").format(new Date()));
System.out.println("main finished!");
//执行结果
Current Time:2017-08-04 14:18:42 星期五
main finished!
Current thread:11, CurrentTime:2017-08-04 14:18:47 星期五
Current thread:12, CurrentTime:2017-08-04 14:18:47 星期五
Current thread:12, CurrentTime:2017-08-04 14:18:49 星期五
Current thread:11, CurrentTime:2017-08-04 14:18:49 星期五
Current thread:12, CurrentTime:2017-08-04 14:18:51 星期五
4. 分支/合并(Fork/Join)框架
//原理
使用“分而治之”算法。其思路是将算法要处理的数据空间拆成较小的独立块,这是“映射”阶段。一旦块集处理完毕之后,就可以将部分结果收集起来形成最终结果,这是“归约”阶段。
一个例子:计算一个大型整数数组的总和。可以将数组划分为较小的部分,并发线程对这些部分计算部分和。然后部分相加,计算总和。此算法在多核架构上可看到明显的性能提升。
//描述
1.fork() 允许执行计划ForkJoinTask一步执行。这允许从现有的ForkJoinTask启动新的ForkJoinTask。
2.join() 允许ForkJoinTask等待另一个ForkJoinTask完成。
RecursiveAction 表示不产生返回值的执行。
RecursiveTask 常用,产生返回值。