第一种,实现Runnable接口
public class MyThread implements Runnable { public void run() { System.out.println("hello world"); } public static void main(String[] args) { MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); } }
第二种,继承Thread类
public class MyThread1 extends Thread { public void run() { System.out.println("hello"); } public static void main(String[] args) { new MyThread1().start(); } }
第三种,实现Callable接口
public class MyThread2 implements Callable<String> { public String call() throws Exception { System.out.println("call----"); return "call"; } public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask<>(new MyThread2()); new Thread(futureTask, "A").start(); System.out.println(futureTask.get()); } }
第四种,通过线程池获取线程
开发规范手册中推荐使用的
不要显式创建线程,请使用线程池。
当然
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
Executors返回的线程池对象的弊端如下:
1)FixedThreadPool和SingleThreadPool
允许的请求队列长度为Integer.MAX_VALUE(约为21亿),可能对堆积大量的请求,从而导致OOM
2)CacheThreadPool和ScheduledThreadPool
允许创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM
/** * 7个参数 * 核心线程池大小 * 最大核心线程池大小 * 超时了没有人调用就会释放 * 超时单位 * 阻塞队列 * 线程工厂:创建线程的,一般不用动Executors.defaultThreadFactory() * 拒绝策略 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handle) { }
四种拒绝策略:
- new ThreadPoolExecutor.AbortPolicy() // 池满了,还有进来的,不处理,抛出异常
- new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!
- new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
- new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!
线程池的最大的大小如何设置?
- CPU 密集型,几核,就是几,可以保持CPU的效率最高!
- IO 密集型,判断程序中十分耗IO的线程
获取CPU的核数
System.out.println(Runtime.getRuntime().availableProcessors());