线程及线程池
1.线程池的作用
限制系统中执行线程的数量
2.为什么要用线程池
2.1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务.
2.2 可以根据系统的承受能力,调整线程池中工作线线程的数目,
防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
3.线程池接口类
3.1 ExecutorService : 真正的线程池接口。
3.2 ScheduledExecutorService:能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。
3.3 ThreadPoolExecutor : ExecutorService的默认实现.
3.4 ScheduledThreadPoolExecutor : 继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。
4.线程池的静态工具类 Executors 常用的方法
4.1 newSingleThreadExecutor
创建一个单线程的线程池,采用无边界队列LinkedBlockingQueue.即线程有限,但队列无限.
4.2 newFixedThreadPool
创建固定大小的线程池,采用无边界队列LinkedBlockingQueue.即线程有限,但队列无限.
4.3 newCachedThreadPool
创建一个可缓存的线程池 ,采用SynchronousQueue队列.
4.4 newScheduledThreadPool
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
5.线程池的执行策略与BlockingQueue
5.1 如果运行的线程少于 corePoolSize(最小线程数量),则 Executor始终首选添加新的线程,而不进行排队.
5.2 如果运行的线程等于或多于 corePoolSize,则 Executor始终首选将请求加入队列,而不添加新的线程。
5.3 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。
6.实例
public class MyThread extends Thread
{
private String name;
public MyThread(String name)
{
this.name = name;
}
@Override
public void run()
{
try
{
Thread.sleep(10000);
System.out.println(Thread.currentThread().getName()+name+"--正在执行!");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
6.1 newSingleThreadExecutor
public class TestSingleThreadExecutor
{
public static void main(String[] args)
{
// 单线程执行
ExecutorService sngleThreadPool = Executors.newSingleThreadExecutor();
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
MyThread t3 = new MyThread("t3");
MyThread t4 = new MyThread("t4");
sngleThreadPool.execute(t1);
sngleThreadPool.execute(t2);
sngleThreadPool.execute(t3);
sngleThreadPool.execute(t4);
sngleThreadPool.shutdown();
}
}
6.2 ScheduledThreadPoolExecutor
public class TestScheduledThreadPool
{
public static void main(String[] args)
{
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable()
{// 每隔一段时间就触发异常
@Override
public void run()
{
System.out.println("================");
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
exec.scheduleAtFixedRate(new Runnable()
{// 每隔一段时间打印系统时间,证明两者是互不影响的
@Override
public void run()
{
System.out.println(System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
}
}
6.3 newFixedThreadPool
public class TestFixedThreadPool
{
public static void main(String[] args)
{
// 多个线程执行,固定大小线程
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
MyThread t3 = new MyThread("t3");
MyThread t4 = new MyThread("t4");
fixedThreadPool.execute(t1);
fixedThreadPool.execute(t2);
fixedThreadPool.execute(t3);
fixedThreadPool.execute(t4);
fixedThreadPool.shutdown();
}
}
6.4 newCachedThreadPool
public class TestCachedThreadPool
{
public static void main(String[] args)
{
// 多个线程执行,无线程数量限制.由运行环境的CPU决定
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
MyThread t3 = new MyThread("t3");
MyThread t4 = new MyThread("t4");
cachedThreadPool.execute(t1);
cachedThreadPool.execute(t2);
cachedThreadPool.execute(t3);
cachedThreadPool.execute(t4);
cachedThreadPool.shutdown();
}
}
6.6 ThreadPoolExecutor
public class TestThreadPoolExecutor
{
public static void main(String[] args)
{
// 通过构造器,创建线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
MyThread t3 = new MyThread("t3");
MyThread t4 = new MyThread("t4");
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.shutdown();
}
}