-
多线程
1.1线程的创建两种方式
重写thread的run方法,或者在初始化线程时给构造参数传一个继承了Runnable接口的对象,其实这两者本身都是将执行体放入run方法。
New Thread(new Runnable{
@overwride
Run(){
}
})
New Thread(){
@overwride
Run(){
}
}
其中方法一更为推荐。
线程池使用ThreadPoolExecutor
1.2线程相关锁
1.Synchronized必须自己控制好同步对象,只有为同一对象才互斥
2.Lock接口,使用了全局变量进行了同步,如果使用同一锁,即使在不同地方也会互斥,需要子类来定义对象Reetrant***,其中又有读写锁,读锁,写锁,锁。
3.线程变量有threadLocal.
4.sleep睡眠和wait等,wait会释放已经有的资源和锁,而sleep不会释放锁,wait可以用notify进行唤醒
1.3线程回调
使用ExecutorService、Callable、Future实现有返回结果的多线程public class Test {
public static void main(String[] args) throws ExecutionException,
InterruptedException {
System.out.println("----程序开始运行----");
Date date1 = new Date();int taskSize = 5;
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 创建多个有返回值的任务
List list = new ArrayList();
for (int i = 0; i < taskSize; i++) {
Callable c = new MyCallable(i + " “);
// 执行任务并获取Future对象
Future f = pool.submit©;
// System.out.println(”>>>" + f.get().toString());
list.add(f);
}
// 关闭线程池
pool.shutdown();// 获取所有并发任务的运行结果
for (Future f : list) {
// 从Future对象上获取任务的返回值,并输出到控制台
System.out.println(">>>" + f.get().toString());
}Date date2 = new Date();
System.out.println("----程序结束运行----,程序运行时间【"
+ (date2.getTime() - date1.getTime()) + “毫秒】”);
}
}class MyCallable implements Callable {
private String taskNum;MyCallable(String taskNum) {
this.taskNum = taskNum;
}public Object call() throws Exception {
System.out.println(">>>" + taskNum + “任务启动”);
Date dateTmp1 = new Date();
Thread.sleep(1000);
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(">>>" + taskNum + “任务终止”);
return taskNum + “任务返回运行结果,当前任务时间【” + time + “毫秒】”;
}
}
1.4线程condition
有点类似wait,需要在lock的前题下使用
1.5线程信号灯
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目, acquire()方法来获取信号灯,release()用来释放信号灯,如果信号灯都用完了,则等待
1.6线程cyclicBarrier
当一个线程的事情处理完了就调用await(),当所有的线程都调用await后,线程继续往下行走,当所有线程阻塞状态被释放后该阻塞可以继续使用。
1.7线程countDownLATCH
和循环阻塞类似,只是阻塞释放后不可继续使用。
1.8线程数据交换
Exchanger类用来做线程数据交换,两交换对象任何一方先拿数据过来,都得等待另一方拿数据过来才能继续向下行走。