方式一:继承Thread 重写run 方法
public class TestThread extends Thread { @Override public void run() { System.out.println("测试Thread-当前线程为:" + Thread.currentThread().getName()); } public static void main(String[] args) { TestThread t1 = new TestThread(); TestThread t2 = new TestThread(); t1.start(); t2.start(); } }
方式二: 实现Runable 重写run 方法
public class TestRunable implements Runnable { @Override public void run() { System.out.println("测试runable-当前线程为:" + Thread.currentThread().getName()); } public static void main(String[] args) { TestRunable t1 = new TestRunable(); TestRunable t2 = new TestRunable(); new Thread(t1).start(); new Thread(t2).start(); } }
方式三 : 实现Callable 重写call 方法
public class TestCallable implements Callable { @Override public Object call() throws Exception { return "callable 多线程返回 : " +Thread.currentThread().getName(); } public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask futureTask = new FutureTask<>(new TestCallable()); new Thread(futureTask).start(); System.out.println(futureTask.get()); } }
方式四:通过线程池来实现
public class MyThreadPool { public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 15, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 25; i++) { Runnable task = new MyRunable(); executor.execute(task); } executor.shutdown(); } }
public class MyRunable implements Runnable { @Override public void run() { System.out.println("当前线程:" + Thread.currentThread().getName() + "运行开始时间:" + new Date()); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程:" + Thread.currentThread().getName() + "运行结束时间:" + new Date()); } }
线程池参数介绍:
- public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
(1)corePoolSize 核心线程数:
线程池新建线程的时候,如果当前线程总数小于corePoolSize,则新建的是核心线程,如果超过corePoolSize,则是非核心线程。
核心线程默认情况下会一直存活在线程池中,可以通过设定ThreadPoolExecutor的 allowCoreThreadTimeOut这个属性为true,那么核心线程超时后就会被销毁掉。
(2) maximumPoolSize 最大线程数:维护着核心线程数+非核心线程数的总数
(3)keepAliveTime 失效时间:设置非核心线程的超时时间,当设置allowCoreThreadTimeOut这个属性为true后 也会作用于核心线程。
(4)unit 时间单位:
- NANOSECONDS : 1微毫秒 = 1微秒 / 1000
- MICROSECONDS : 1微秒 = 1毫秒 / 1000
- MILLISECONDS : 1毫秒 = 1秒 /1000
- SECONDS : 秒
- MINUTES : 分
- HOURS : 小时
- DAYS : 天
(5)workQueue 任务队列:
当核心线程满了之后,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务
- SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现线程数达到了maximumPoolSize而不能新建线程的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE
- LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
- ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误
- DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
(6)threadFactory:创建新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等。
(7)RejectedExecutionHandler 拒绝策略:
- AbortPolicy :直接丢弃该任务,并抛出RejectedExecutionException异常
public static class AbortPolicy implements RejectedExecutionHandler { /** * Creates an {@code AbortPolicy}. */ public AbortPolicy() { } /** * Always throws RejectedExecutionException. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task * @throws RejectedExecutionException always */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
- CallerRunsPolicy :该线程池没有shutdown 则直接run 该拒绝的任务
public static class CallerRunsPolicy implements RejectedExecutionHandler { /** * Creates a {@code CallerRunsPolicy}. */ public CallerRunsPolicy() { } /** * Executes task r in the caller's thread, unless the executor * has been shut down, in which case the task is discarded. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } }
- DiscardPolicy:直接丢弃任务
public static class DiscardPolicy implements RejectedExecutionHandler { /** * Creates a {@code DiscardPolicy}. */ public DiscardPolicy() { } /** * Does nothing, which has the effect of discarding task r. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }
- DiscardOldestPolicy:线程池没有shutdown情况下 抛弃进入队列最早的那个任务,然后把这次拒绝的任务放入队列
public static class DiscardOldestPolicy implements RejectedExecutionHandler { /** * Creates a {@code DiscardOldestPolicy} for the given executor. */ public DiscardOldestPolicy() { } /** * Obtains and ignores the next task that the executor * would otherwise execute, if one is immediately available, * and then retries execution of task r, unless the executor * is shut down, in which case task r is instead discarded. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } }