一对线程解
在平时工作中肯定会遇到关于线程的问题,在日常工作中,我们创建线程一般都是两种方式,实现Runnable接口或者继承thread类,这两种方式看过源码的都知道,其实Thread 也是实现Runnable接口。区别就是运行的过程有点不一样,因为线程运行最后都需要调用thread的run方法,如果是直接继承thread,thread里面的run方法被重写,就调用子类的run模块,如果是实现Runnable接口,则需要把实现Runnable 类的实例,传给thread类并且调用thread的run方法,这感觉有点像我学习中的简单代理模式。thread和实现Runnable 类的类都实现Runnable接口,thread 还代理运行实现Runnable 类的实例的方法。thread源码如下
再看看实现runable接口实例调用run方法,
这里也是学习过程中遇到的记录下来。
二线程池的理解
创建线程任务的时候,不管以哪种方式,都是可以的 ,看你个人喜欢,但是当遇到成千上万的请求的时候,如果我么面对每一次请求都创建一个线程,那得 耗多少内存,浪费多少资源,请求速度也很慢,如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
所以有没有一个方法来解决这个问题呢,让线程可以重复使用,所有的请求都按照顺序存放在一个队里里,批次处理请求。
线程池就是这种解决方案。
三具体代码实现
package thread
;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
public class ThreadPool {
private WorkThread[] workThread ;
//public static Thread1 t1=null;
public LinkedList<Runnable> taskQueue= new LinkedList<Runnable>();//存放任务线程的队列
public ThreadPool(){//当类实例化的时候会创建五个工作线程,用来工作
this(5);
}
private ThreadPool(int num){
workThread=new WorkThread[num];
for(int i=0;i<num;i++){
workThread[i]=new WorkThread();
workThread[i].start();
}
}
public void addThread(Runnable[] task){//把任务线程添加到队列里,等待执行
synchronized (taskQueue) {//添加任务的时候释放队列锁
for(Runnable r:task){
taskQueue.add( r);
taskQueue.notify();
}
}
}
public static void main(String[] args) {
/* Thread2 t2=new Thread1().new Thread2();
Thread3 t3=new Thread1().new Thread3();
t2.start();
t3.start();*/
ThreadPool t=new ThreadPool(2);
t.addThread(new Runnable [] {new ThreadPool().new task(),new ThreadPool().new task(),new ThreadPool().new task2()} );//添加任务
}
public class WorkThread extends Thread{//五个工作线程,分别调用任务线程的run 方法,因为队列里面存放的是任务线程的实例
private boolean isAlive=true;
private Runnable r=null;
public void run() {
while(isAlive){
synchronized(taskQueue){
while(isAlive&&taskQueue.isEmpty()){//如果队列还没有任务线程,工作线程会一直等待,直到有任务的时候工作
try {
taskQueue.wait(2000);//线程上锁时间
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
r=taskQueue.remove(0);//执行完一个任务就移除
if(r!=null){
r.run();
}
}
r=null;
}
}
}
public class task implements Runnable{//任务线程,会被实例化放到队列里面
public void run(){
System.out.println("1111");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
System.out.println(df.format(new Date()));// new Date()为获取当前系统时间
}
}
public class task2 implements Runnable{//任务线程,会被实例化放到队列里面
public void run(){
System.out.println("222");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
System.out.println(df.format(new Date()));// new Date()为获取当前系统时间
}
}
}
我总结的线程池实现思想是。创建五个工作线程,这个五个工作线程会一直等待并且执行队列里的任务,即调用任务线程的run方法。不再像传统的,创建一个线程就立马调用run方法。线程池把这个调用run的方法让工作线程来控制了,这样不管多少任务,多少请求(每一个任务每一个请求都是一个线程),每次只能完成五个。
这是我理解的线程池实现原理,至于其他的 ,比如jdk 中使用的线程池,四种实现方式应该是在这个基础上加以改良,做各种限制操作等。