1. 创建线程的三种方式:
- 继承Thread,重写run方法
- 实现Runnable接口,重新run方法
- 实现Callable接口,重写call方法
1,
package com.snjx.demo.multithread; /** * 多线程学习 * Thread */ public class ThreadTest extends Thread{ private int count=10; @Override public void run() { for (int i = 0; i <count; i++) { if (this.count>0) { try { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "抢到了" + count-- + "号票"); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { ThreadTest test=new ThreadTest(); new Thread(test,"旅客甲").start(); new Thread(test,"旅客已").start(); new Thread(test,"二狗子").start(); } }
2,
package com.snjx.demo.multithread; /** * 多线程学习 * Runnable */ public class RunnableTest implements Runnable { private int count=30; /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see Thread#run() */ @Override public void run() { for (int i = 0; i <count ; i++) { if (count<=0) { break; } System.out.println(Thread.currentThread().getName()+"抢到了"+count--+"号票"); } } public static void main(String[] args) { RunnableTest web=new RunnableTest(); Thread t1=new Thread(web,"旅客甲"); Thread t2=new Thread(web,"旅客已"); Thread t3=new Thread(web,"二狗子"); t1.start(); t2.start(); t3.start(); } }
3,
Callable接口实际上是属于Executor框架中的功能类,Callable接口与Runnable接口的功能类似,但提供了比Runnable更加强大的功能。
- Callable可以在任务结束的时候提供一个返回值,Runnable无法提供这个功能
- Callable的call方法分可以抛出异常,而Runnable的run方法不能抛出异常。
package com.snjx.demo.multithread; import java.util.concurrent.*; /** * 多线程学习 * Callable */ public class CallableTest { } class MyThread implements Callable<String> { private String name; public MyThread(String name) { this.name = name; } /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ @Override public String call() throws Exception { return " Hello Callable "; } public static void main(String[] args) { MyThread t1 = new MyThread("旅客甲"); MyThread t2 = new MyThread("旅客已"); MyThread t3 = new MyThread("二狗子"); //开启的线程数 ExecutorService service = Executors.newFixedThreadPool(3); Future f1 = service.submit(t1); Future f2 = service.submit(t2); Future f3 = service.submit(t3); try { String o1 = f1.get().toString(); String o2 = f2.get().toString(); String o3 = f3.get().toString(); System.out.println(t1.name+o1+t2.name+o2+t3.name+o3); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }finally { service.shutdownNow(); } } }
二、线程池
创建线程池主要有三个静态方法供我们使用,由Executors来进行创建相应的线程池:
public static ExecutorSevice newSingleThreadExecutor()
public static ExecutorSevice newFixedThreadPool(int nThreads)
public static ExecutorSevice newCachedThreadPool()
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
- 1
- 2
- 3
- 4
- newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代。
- newFixedThreadPool返回一个包含指定数目线程的线程池,如果任务数量多于线程数量,那么没有执行的任务必须等待,直到有任务完成为止。
- newCachedThreadPool根据用户的任务数创建相应的线程来处理,该线程池不会对线程数目加以限制,完全依赖于JVM能创建线程的数量,可能引起内存不足。
- newScheduledThreadPool创建一个至少有n个线程空间大小的线程池。此线程池支持定时以及周期性执行任务的需求。
我们只需要把实现了Runnable的类的对象实例放入线程池,那么线程池就自动维护线程的启动、运行、销毁。我们不需要自行调用start()方法来开启这个线程。线程放入线程池之后会处于等待状态直到有足够空间时会唤醒这个线程。
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(socketThread);
//至少维护5个线程容量的空间
private ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);
//函数意义:一个线程开始之后和下一个线程开始的时间间隔
//第一个时间参数表示初始化执行延迟1000毫秒,第二个时间参数表示每隔1000毫秒执行一次
//第二个线程必须等到第一个线程执行完成才能继续执行,尽管时间间隔小于线程执行时间
threadPool.scheduleAtFixedRate(socketThread, 1000, 1000, TimeUnit.MILLISECONDS);
//基本参数和上面的类似,函数意义不一样:一个线程结束之后和下一个线程开始的时间间隔
threadPool.scheduleWithFixedDelay(socketThread, 1000, 1000, TimeUnit.MILLISECONDS);
//线程池不接收新加的线程,但是执行完线程池内部的所有线程
threadPool.shutdown();
//立即关闭线程池,停止线程池内还未执行的线程并且返回一个未执行的线程池列表
threadPool.shutdownNow();