java的多线程学习,第四记
假如写网络编程的程序,socket编程就是响应客户编程的服务端。
public class ThreadPool { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(80); while (true){ Socket socket = serverSocket.accept(); Runnable task = new Runnable() { @Override public void run() { handleRequest(socket); } }; new Thread(task).start(); } } private static void handleRequest(Socket socket) { } }
这样做,每来一个就创建一个线程,会出现很多问题的。java虚拟机就挂掉了,内存溢出。
资源消耗得不到限制,并不能控制线程的数量。
//Executor 线程池
创建线程池
Executor executor = Executors.newFixedThreadPool(100);
拥有100线程的线程池。
Executor executor1 = Executors.newSingleThreadExecutor();
池子里,永远只有一个线程。平常如果new一个线程,挂掉了就没有了。
single这个如果被占用了,就阻塞这里等着,如果有异常了,就拿一条新的线程。
Executor executor2 = Executors.newCachedThreadPool();
这个是缓冲线程池,不知道有多少个线程。来一个创建一个,来一个创建一个。没有上限的。
Executor是个接口,ExecutorService是个子类。
线程池的任务丢进去是不可控的,什么时间关闭,如果executor没有运行完,jvm是不可能关闭的,除非你强行关闭电源。
ExecutorService提供了关闭的方法。
List<Runnable> shutdownNow(); void shutdown(); boolean isTerminated();
线程池有三种状态:
1,运行状态。running
2,关闭状态。shutdown状态,不是立即终止,停止接受新的任务,但是等待提交的任务完成。
3,终止状态。什么任务都完成了。把线程池掐掉。
shutdownNow返回还没有执行完的任务的线程。isTerminated是所有线程都死掉了。
tomcat源码用的exector,解析http协议。
public class ThreadPool { static ExecutorService executor = Executors.newFixedThreadPool(100); //Executor 线程池 public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(80); while (!executor.isShutdown()){ Socket socket = serverSocket.accept(); try { executor.execute(new Runnable() { @Override public void run() { handleRequest(socket); } }); //RejectedExecutionException 拒绝执行任务异常 } catch (RejectedExecutionException e) { if (!executor.isShutdown()){ System.out.println("线程池接受任务被拒绝"); throw e; } } } } public void stop(){ executor.shutdown(); } private static void handleRequest(Socket socket) { } }
Executors.newScheduledThreadPool();
java的定时任务的执行,可调度的定时任务的执行。
public class Shedule { private static long start; private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); public static void main(String[] args) { TimerTask task = new TimerTask() { @Override public void run() { System.out.println(System.currentTimeMillis()-start); try{ Thread.sleep(3000); }catch (InterruptedException e){ e.printStackTrace(); } } }; TimerTask task1 = new TimerTask(){ @Override public void run() { System.out.println(System.currentTimeMillis()-start); } }; Timer timer = new Timer(); start = System.currentTimeMillis(); //启动一个调度任务,delay延迟毫毛单位 timer.schedule(task,1000); timer.schedule(task1,3000); } }
用Timer,线程之间是相互干扰的。Timer是个单线程。
public class Shedule { private static long start; private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); public static void main(String[] args) { TimerTask task = new TimerTask() { @Override public void run() { System.out.println(System.currentTimeMillis()-start); try{ Thread.sleep(3000); }catch (InterruptedException e){ e.printStackTrace(); } } }; TimerTask task1 = new TimerTask(){ @Override public void run() { System.out.println(System.currentTimeMillis()-start); } }; // Timer timer = new Timer(); start = System.currentTimeMillis(); //启动一个调度任务,delay延迟毫毛单位 // timer.schedule(task,1000); // timer.schedule(task1,3000); executorService.schedule(task,1000, TimeUnit.MILLISECONDS); executorService.schedule(task,3000, TimeUnit.MILLISECONDS); } }
如果第一个线程异常了,那么就阻塞在这了。
public class Shedule { private static long start; private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); public static void main(String[] args) { TimerTask task = new TimerTask() { @Override public void run() { throw new RuntimeException(); } }; TimerTask task1 = new TimerTask(){ @Override public void run() { System.out.println(System.currentTimeMillis()-start); } }; Timer timer = new Timer(); start = System.currentTimeMillis(); //启动一个调度任务,delay延迟毫毛单位 timer.schedule(task,1000); timer.schedule(task1,3000); // executorService.schedule(task,1000, TimeUnit.MILLISECONDS); // executorService.schedule(task,3000, TimeUnit.MILLISECONDS); } }
executorService用的是相对时间,不是系统时间。
用那些pool,实际上底层返回的是ThreadPoolExecutor返回的。
public ThreadPoolExecutor(int corePoolSize,//线程数量 int maximumPoolSize,//最大的线程数量 long keepAliveTime,//线程活跃的时间是多少 TimeUnit unit,//时间单位 BlockingQueue<Runnable> workQueue//里面装的是Runnable 并发容器 workQueue工作队列) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
executor接口,关闭不是很好关闭。
Executors是工具类,可以搞线程池这些东西。这里面的方法最终弄的是ThreadPoolExecutor。都可以指定的。