用户写线程有两种方式
方式一:
用户自己写线程的并发
Runnable r=new Runnable(){重写run方法}
Thread t1=new Thread(r);
Thread t2=new Thread(r);
...
用户要自己控制线程对象的作用域,
相当于用户自己来管理线程
方式二:
java给提供一个线程池的概念
线程池:把若干用户线程添加到线程池中,由线程池来管理线程
为什么要使用线程池:
- 减少了创建和销毁线程的次数,每个工作线程都可以被重复使用
或利用,可以并发执行多个任务 - 可以根据系统的承受能力,调整线程池中的工作线程的数目
防止因为消耗过多的内存,而使服务器宕机(down)
结论:就是java给提供一个写api方法,用于更好的管理线程,
让程序员主要用于写线程逻辑
线程池的使用:
有一个Executors的线程工具类,此类提供了若干静态方法,
这些静态方法用于生成线程池的对象
-
Executors.newSingleThreadExecutor();
创建一个单线程的线程池,这个线程池只有一个线程在工作
即,单线程执行任务,如果这个唯一的线程因为异常结束,
那么会有一个新的线程来替代他,因此线程池保证所有的任务
是按照任务的提交的顺序来执行 -
Executors.newFilxedThreadPool()
创建固定大小的线程池,每次提交一个任务就创建一个线程
直到线程达到线程池的最大大小,线程池的大小一旦达到最大
就会保持不变,如果某个线程因为执行异常而结束,那么就会
补充一个新的线程 -
Executors.newCacheedThreadPool();
创建一个可以缓冲的线程池,如果线程大小超过了处理的任务
所需要的线程,那么就回收部分线程,当任务数增加的时候,此
线程池又可以智能的添加新的线程来处理任务
此线程池不会对线程池大小做限制,线程池的大小完全依赖操作
系统能够创建的最大的大小 -
Executors.newScheduledThreadPool();
创建一个大小无限制的线程池,此线程池支持定时以及周期性
的执行任务的需求
线程逻辑类:
public class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"正在执行...");
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
-
Executors.newSingleThreadExecutor();
创建一个单线程的线程池,这个线程池只有一个线程在工作
即,单线程执行任务,如果这个唯一的线程因为异常结束,
那么会有一个新的线程来替代他,因此线程池保证所有的任务
是按照任务的提交的顺序来执行import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** *Executors.newSingleThreadExecutor(); *创建一个单线程的线程池,这个线程池只有一个线程在工作 *即,单线程执行任务,如果这个唯一的线程因为异常结束, *那么会有一个新的线程来替代他,因此线程池保证所有的任务 *是按照任务的提交的顺序来执行 * @author ZhangYang * */ public class TestExecutors_SingleThreadExecutor { public static void main(String[] args) { ExecutorService pool=Executors.newSingleThreadExecutor(); //创建若干线程 MyThread mt1=new MyThread(); MyThread mt2=new MyThread(); MyThread mt3=new MyThread(); MyThread mt4=new MyThread(); MyThread mt5=new MyThread(); //把线程提交个线程池 pool.execute(mt1); pool.execute(mt2); pool.execute(mt3); pool.execute(mt4); pool.execute(mt5); //关闭线程池 pool.shutdown(); } }
-
Executors.newFilxedThreadPool()
创建固定大小的线程池,每次提交一个任务就创建一个线程
直到线程达到线程池的最大大小,线程池的大小一旦达到最大
就会保持不变,如果某个线程因为执行异常而结束,那么就会
补充一个新的线程import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 2.Executors.newFilxedThreadPool() * 创建固定大小的线程池,每次提交一个任务就创建一个线程 * 直到线程达到线程池的最大大小,线程池的大小一旦达到最大 * 就会保持不变,如果某个线程因为执行异常而结束,那么就会 * 补充一个新的线程 * @author ZhangYang * */ public class TestExecutors_FixedThreadExecutor { public static void main(String[] args) { ExecutorService pool=Executors.newFixedThreadPool(2); //创建若干线程 MyThread mt1=new MyThread(); MyThread mt2=new MyThread(); MyThread mt3=new MyThread(); MyThread mt4=new MyThread(); MyThread mt5=new MyThread(); //把线程提交个线程池 pool.execute(mt1); pool.execute(mt2); pool.execute(mt3); pool.execute(mt4); pool.execute(mt5); //关闭线程池 pool.shutdown(); } }
-
Executors.newCacheedThreadPool();
创建一个可以缓冲的线程池,如果线程大小超过了处理的任务
所需要的线程,那么就回收部分线程,当任务数增加的时候,此
线程池又可以智能的添加新的线程来处理任务
此线程池不会对线程池大小做限制,线程池的大小完全依赖操作
系统能够创建的最大的大小import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Executors.newCacheedThreadPool(); * 创建一个可以缓冲的线程池,如果线程大小超过了处理的任务 * 所需要的线程,那么就回收部分线程,当任务数增加的时候,此 * 线程池又可以智能的添加新的线程来处理任务 * 此线程池不会对线程池大小做限制,线程池的大小完全依赖操作 * 系统能够创建的最大的大小 * @author PC * */ public class TestExecutors_CachedThreadExecutor { public static void main(String[] args) { ExecutorService pool=Executors.newCachedThreadPool(); //创建若干线程 MyThread mt1=new MyThread(); MyThread mt2=new MyThread(); MyThread mt3=new MyThread(); MyThread mt4=new MyThread(); MyThread mt5=new MyThread(); //把线程提交个线程池 pool.execute(mt1); pool.execute(mt2); pool.execute(mt3); pool.execute(mt4); pool.execute(mt5); //关闭线程池 pool.shutdown(); } }
-
Executors.newScheduledThreadPool();
创建一个大小无限制的线程池,此线程池支持定时以及周期性的执行任务的需求import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Executors.newScheduledThreadPool(); * 创建一个大小无限制的线程池,此线程池支持定时以及周期性 * 的执行任务的需求 * @author ZhangYang * */ public class TestExecutors_ScheduledThreadExecutor { public static void main(String[] args) { ScheduledExecutorService pool=Executors.newScheduledThreadPool(1); pool.scheduleAtFixedRate(new Runnable(){ public void run(){ System.out.println("计划执行run"); } }, 2000, 5000, TimeUnit.MILLISECONDS); //注意不能关闭线程池 // pool.shutdown(); } }
另:手动创建线程池
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 此类演示手动创建线程池
* @author ZhangYang
*
*/
public class TestExecutorService {
public static void main(String[] args) {
//手动创建了一个线程池
ThreadPoolExecutor threadPool=new ThreadPoolExecutor(5,10,30L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(5),new RejectedExecutionHandler(){
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("线程数超过了线程池的容量,拒绝指行任务-->"+r);
}
});
//把线程放在线程池中,并执行
threadPool.execute(new TestThread(1));
threadPool.execute(new TestThread(2));
threadPool.execute(new TestThread(3));
threadPool.execute(new TestThread(4));
threadPool.execute(new TestThread(5));
threadPool.execute(new TestThread(6));
threadPool.execute(new TestThread(7));
threadPool.execute(new TestThread(8));
threadPool.execute(new TestThread(9));
threadPool.execute(new TestThread(10));
threadPool.execute(new TestThread(11));
threadPool.execute(new TestThread(12));
threadPool.execute(new TestThread(13));
threadPool.execute(new TestThread(14));
threadPool.execute(new TestThread(15));
threadPool.execute(new TestThread(16));
threadPool.execute(new TestThread(17));
}
}
/**
* 写线程的任务逻辑
* @author tedu
*
*/
class TestThread implements Runnable{
private int num;
public TestThread(int num){
this.num=num;
}
@Override
public void run() {
try {
System.out.println("第"+num+"号线程开始执行");
Thread.sleep(3000);
System.out.println("第"+num+"号线程开始结束");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}