最近,由于课题项目进度,需要设计解决多线程方面的处理,于是复习了一遍基础知识,整理了一下,理解有误还请大家指正,后期持续更新。
并发的优势:
主要的问题:速度和设计管理
1,更快的执行 2,改进代码的设计
实现方式:
1,进程实现,比较简单,不涉及资源冲突,PHP就是通过多进程实现的
2,线程实现,比较复杂,需要解决资源问题。
编写多线程程序最基本的困难在于协调不同线程驱动的任务之间对这些资源的使用,以使用这些资源不会同时被多个任务访问。
一实现线程的方式
1,Thread类
2,实现Runnable接口
3,Executor:
管理异步任务的执行,而无须显示地管理线程的生命周期。从J2SE5.0以后,为启动任务的优选方法
1)shutdown()调用可以防止新任务被提交,这个程序将在Exectutor中的所有任务完成之前尽快退出。
2)四种线程池:
CachedThreadPool,在程序执行过程中创建与所需数量相同的线程,在回收旧线程时,会停止创建新线程,因此它是合理的Executor。当有问题切换到FixedThreadPool
FixThreadPool:可以一次性支付执行代价高昂的线程分配,可以限制线程的数量,节省时间,不用为每个任务都固定地付出创建线程的开销。
SigleThreadPool:线程数量唯一的FixedThreadPool,会序列化所有提供的任务,并会维护自己的悬挂任务队列。
二,线程中得到返回值
1,实现Callable接口
2,必须使用ExecutorService.submit(),从call方法中得到返回值
三,线程的休眠
1,sleep();任务中止执行该定的时间,在5.0以后,引入了显示的sleep版本,TimeUtil,可以指定休眠的时间单位。
注意:休眠期间,线程仍然持有锁。
四,线程的优先级
线程的优先级在使用中不太可靠,不能只想着通过优先级,即可一直或长时间执行某个线程。优先级低的线程仅仅是执行的频率较低。
此外,线程的优先级与操作系统的优先级并不能一一映射,javaSdk有10个优先级。Window操作系统有七个优先级。唯一可以映射的时,当调整优先级时,只使用:MIN_PRIORITY,NORM_PRIORITY MAX_PRIORITY
具体代码:
package learn;
import java.util.concurrent.TimeUnit;
/**
* Created by acer on 2016/2/27.
*/
public class LifOff implements Runnable {
// 定义相关的变量
protected int countdown = 10; //default
private static int takeCount = 0;
private final int id = takeCount++;
public LifOff() {
}
public LifOff(int countdown) {
this.countdown = countdown;
}
@Override
public void run() {
while (countdown-- > 0) {
System.out.print(status());
Thread.yield();
//显示的休眠线程
// TimeUnit.MINUTES.sleep(time);
}
}
private String status() {
return "#" + id + "(" + (countdown > 0 ? countdown : "liftoff") + "),";
}
}
package learn;
import java.util.concurrent.Callable;
/**
* Created by acer on 2016/2/28.
*/
public class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
@Override
public String call() throws Exception {
return "result of the taskwithreuslt :" + id + "\n";
}
}
package learn;
import Util.PrintUtil;
/**
* Created by acer on 2016/2/28.
*/
public class SimplePriorty implements Runnable{
private int countdown = 5;
private volatile double d;
private int proioty;
@Override
public String toString() {
return Thread.currentThread() + "," + countdown;
}
public SimplePriorty(int proioty) {
this.proioty = proioty;
}
@Override
public void run() {
// 在此设置即可,在构造器重直接设置优先级没有太大价值,因为还没有执行
Thread.currentThread().setPriority(proioty);
while (true) {
for (int i=0; i<100000; i++) {
d += (Math.PI + Math.E ) / (double)i; //具体的复杂操作,增加执行时间,使得线程调度可以实现
if (i % 1000 == 0) {
Thread.yield();
}
PrintUtil.printb(this); //调用的toString方法
}
if (--countdown == 0) {
return;
}
}
}
}
package learn;
import Util.PrintUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* Created by acer on 2016/2/27.
*/
public class Main {
public static void main(String args[]) {
// //第二种
// pruductThreada();
// 第三中,也是推荐的方法
//goodThreadb();
// 线程返回值
// resultThread();
// 测试优先级
//proiortyThread();
// 后台线程
//deamonThread();
// 加入
//joinShow();
//异常演示证明无法捕获
//noCatchExp();
}
private static void noCatchExp() {
try {
ExecutorService excepSer = Executors.newCachedThreadPool();
excepSer.execute(new ExceptionThread());
excepSer.shutdown();
} catch (RuntimeException e) {
PrintUtil.printb(e.getLocalizedMessage());
}
}
private static void joinShow() {
Sleeper
sleepy = new Sleeper("Sleep",1500),
grom = new Sleeper("grom",1500);
Joiner
dopey = new Joiner("Dopey", sleepy),
doc = new Joiner("doc",grom);
grom.interrupt();
}
private static void deamonThread() {
Thread tt = new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
PrintUtil.printb("HOUTAI");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
tt.setDaemon(true); //start前调用
tt.start();
PrintUtil.printb(" all deamon is start");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void proiortyThread() {
ExecutorService service2 = Executors.newCachedThreadPool();
for (int i =0; i<5; i++) {
service2.execute(new SimplePriorty(Thread.MIN_PRIORITY));
service2.execute(new SimplePriorty(Thread.MAX_PRIORITY));
}
service2.shutdown();
}
private static void resultThread() {
ExecutorService valueSer = Executors.newCachedThreadPool();
//存储返回的结果
List<Future<String>> result = new ArrayList<Future<String>>();
for(int j=0; j<5; j++) {
//返回必须使用此方法,返回的值封装在Future中
result.add(valueSer.submit(new TaskWithResult(j)));
}
for (Future<String> fs: result) {
try {
PrintUtil.printa(fs.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
valueSer.shutdown();
}
}
}
private static void goodThreadb() {
ExecutorService service = Executors.newCachedThreadPool();
for (int i =0; i<5; i++) {
service.execute(new LifOff());
}
service.shutdown();
ExecutorService service1 = Executors.newSingleThreadExecutor();
for (int i =0; i<5; i++) {
service1.execute(new LifOff());
}
service.shutdown();
}
private static void pruductThreada() {
Thread tt = new Thread(new LifOff());
tt.start();
PrintUtil.printa("wait for lifoff");
}
}
五,让步
调用yield()方法,建议具有相同优先级的其他线程可以运行,但不一定会运行,只是暗示。
官方解释:
/**
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
*
*
Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*
*
It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
六,后台线程,
后台线程:程序运行过程中,在后台提供一种通用服务的线程,不属于程序不可或缺的部分,当所有的非后台线程结束时,程序也终止,会杀死所有的后台线程
使用:再启动之前,setDeamon(true)即可
isDeamon确定一个线程是否为后台线程
七,加入一个线程
使用介绍:
1)a线程在other线程之上调用join()方法,效果就是等待一段时间直到a线程结束才继续执行other线程。
2)对join()方法的调用可以被中断,做法是调用线程上的interrupt()方法。
八,捕获异常:
由于线程的本质,我们无法捕捉从线程中逃逸的异常,一旦异常逃出任务的run方法,将向外传播到控制台
此时,在main方法中try,catch捕捉异常没有任何作用
要捕获异常,使用Thread.UncaughtExceptionHandler这个接口,同时定制自己的线程。让在每一个线程都有异常处理器
package learn.excepCatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* Created by acer on 2016/2/28.
*/
public class CaptureUncaughtException {
public static void main(String args[]) {
ExecutorService service = Executors.newCachedThreadPool(new MyThreadFactory());
service.execute(new ExceptionThreadTwo());
// service.shutdown();
}
}
package learn.excepCatch;
import Util.PrintUtil;
import java.util.concurrent.ThreadFactory;
/**
*定制自己的线程
* Created by acer on 2016/2/28.
*/
public class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
PrintUtil.printb(this + "is createing the new Thread");
Thread thread = new Thread(r);
PrintUtil.printb("created Thread is :" + thread);
thread.setUncaughtExceptionHandler(new MyCatchExceptionHandler());
PrintUtil.printb("threadException Handler is :" + thread.getUncaughtExceptionHandler());
return thread;
}
}
package learn.excepCatch;
import Util.PrintUtil;
/**自己定义的异常处理工具类
* Created by acer on 2016/2/28.
*/
public class MyCatchExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
PrintUtil.priintall("catch :"+ e);
}
}
package learn.excepCatch;
import Util.PrintUtil;
/**
* Created by acer on 2016/2/28.
*/
public class ExceptionThreadTwo implements Runnable{
@Override
public void run() {
Thread t = Thread.currentThread();
PrintUtil.printb("run by : " + t);
PrintUtil.printb("exceptionHandler : " + t.getUncaughtExceptionHandler());
throw new RuntimeException("the exception will be catched");
}
}