【Java】多线程初探
Java的线程状态
- getState方法:返回该线程的状态,可能是NEW, RUNNABLE, BLOCKED, WAITING, TIME_WAITING, TEMINATED之一
- getName: 返回线程名称
- getPriority: 返回线程优先级
public class MyThread extends Thread{ @Override public void run() { System.out.println("线程状态:" + Thread.currentThread().getState()); System.out.println("线程名称:" + Thread.currentThread().getName()); System.out.println("线程优先级:" + Thread.currentThread().getPriority()); } public static void main (String args []) { MyThread t = new MyThread(); t.start(); } }
输出:
线程状态:RUNNABLE 线程名称:Thread-0 线程优先级:5
线程的创建和启动
一. 继承Thread类创建线程
public class MyThread extends Thread { private int i = 0; public void run () { i++; System.out.println(i); } public static void main (String args []){ MyThread t = new MyThread(); t.start(); } }
1
二. 实现Runnable接口创建线程
public class MyRunnable implements Runnable { private int i =0; @Override public void run() { i++; System.out.println(i); } }
Test.java
public class Test { public static void main (String args[]) { Thread t = new Thread(new MyRunnable()); t.start(); } }
输出
1
三. 通过Callable接口和Future接口创建线程
public interface Future<V> { V get () throws ...; // 当任务完成时, 获取结果 V get (long timeout, TimeUnit unit); // 在get方法的基础上指定了超时时间 void cancel ( boolean mayInterupt); // 取消任务的执行 boolean isDone (); // 任务是否已完成 boolean isCancel (); // 任务是否已取消 }
- 对于Callable对象来说, Future对象可帮助它保存结果信息,当调用get方法的时候将会发生阻塞, 直到结果被返回。
- 而对于Runnable对象来说, 无需保存结果信息, 所以get方法一般为null, 这里Future的作用主要是可以调用cancel方法取消Runnable任务
FutureTask task = new FutureTask(new Callable);
得到的task既是一个Runnable也是一个Future。这样一来,可以先把得到的task传入Thread构造函数中创建线程并运行(作为Runnable使用), 接着通过task.get以阻塞的方式获得返回值(作为Future使用)
import java.util.concurrent.Callable; public class MyCallable implements Callable { @Override public Object call() throws Exception { Thread.sleep(1000); return "返回值"; } }
Test.java
import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class Test { public static void main (String args []) throws ExecutionException, InterruptedException { // task同时实现了Runnable接口和Future接口 FutureTask task = new FutureTask(new MyCallable()); // 作为 Runnable 使用 Thread t = new Thread(task); t.start(); // 作为Future使用, 调用get方法时将阻塞直到获得返回值 System.out.println(task.get()); } }
返回值
四.通过线程池创建线程
public interface Executor { void execute(Runnable command); }
public interface ExecutorService extends Executor { void shutdown(); <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); // 其他方法 }
- 调用submit方法可以将Runnable或Callable实例提交给线程池里的空闲线程执行,同时返回一个Future对象, 保存了和执行结果有关的信息
- 当线程池用完时, 需要调用 shutdown方法关闭线程
public class Executors { public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } }
public class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i<3;i++) { System.out.println("MyRunnable正在运行"); } } }
import java.util.concurrent.Callable; public class MyCallable implements Callable{ @Override public Object call() throws Exception { for (int i=0;i<3;i++) { System.out.println("MyCallable正在运行"); } return "回调参数"; } }
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Test { public static void main (String args []) throws ExecutionException, InterruptedException { // 创建一个固定数量为2的线程池 ExecutorService service = Executors.newFixedThreadPool(2); // 向线程池提交Callable任务,并将结果信息保存到Future中 Future callableFuture = service.submit(new MyCallable()); // 向线程池提交Runnable任务,并将结果信息保存到Future中 Future runnableFuture = service.submit(new MyRunnable()); // 输出结果信息 System.out.printf("MyCallable, 完成:%b取消:%b返回值:%s%n", callableFuture.isDone(), callableFuture.isCancelled(), callableFuture.get()); System.out.printf("MyRunnable, 完成:%b取消:%b返回值:%s%n", runnableFuture.isDone(), runnableFuture.isCancelled(), runnableFuture.get()); // 关闭线程池 service.shutdown(); } }
MyCallable正在运行 MyCallable正在运行 MyCallable正在运行 MyCallable, 完成:true取消:false返回值:回调参数 MyRunnable正在运行 MyRunnable正在运行 MyRunnable正在运行 MyRunnable, 完成:false取消:false返回值:null
线程的运行
线程的阻塞(广义)
- 阻塞(Blocked)是试图获得对象锁(不是java.util.concurrent库中的锁),而对象锁暂时被其他线程持有导致
- 等待(Waiting)则是调用Object.wait,Thread.join或Lock.lock等方法导致的
- 计时等待(Time waiting)则是在等待的方法中引入了时间参数进入的状态,例如sleep(s)
线程的终止
1. 共享变量结束线程
public class InteruptSimulation implements Runnable{ private volatile static boolean stop = false; @Override public void run() { try { while (!stop) { System.out.println("线程正在运行"); // 休眠5秒 Thread.sleep(5000); } System.out.println("线程终止"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main (String args []) throws InterruptedException { Thread t = new Thread(new InteruptSimulation()); t.start(); // 休眠1秒 Thread.sleep(1000); // 将共享变量stop置为true stop = true; } }
// 运行后立即输出 线程正在运行 // 大约在5秒后才输出 线程终止
2. 利用中断机制结束线程
public class InteruptReal implements Runnable{ @Override public void run() { try { while (!Thread.currentThread().isInterrupted()) { System.out.println("线程正在运行"); Thread.sleep(5000); } } catch (InterruptedException e) { // 发生中断异常后,中断状态位被置为false,这里再次置为true Thread.currentThread().interrupt(); } System.out.println("是否中断:"+Thread.currentThread().isInterrupted()); System.out.println("线程状态:"+Thread.currentThread().getState()); } public static void main (String args []) throws InterruptedException { Thread t = new Thread(new InteruptReal()); t.start(); // 休眠1s Thread.sleep(1000); t.interrupt(); } }
输出:
线程正在运行 // 1s后输出 是否中断:true 线程状态:RUNNABLE
线程现在已经能够及时退出啦
线程的常用方法调用
Thread.sleep
Thread.yeild
Thread.join
public class JoinRunnable implements Runnable{ @Override public void run() { for(int i=0;i<3;i++) { System.out.println(Thread.currentThread().getName()+ "正在执行"); } } public static void main (String args[]) throws InterruptedException { Thread t = new Thread(new JoinRunnable()); t.start(); System.out.println("子线程执行完毕"); } }
子线程执行完毕 Thread-0正在执行 Thread-0正在执行 Thread-0正在执行
public class JoinRunnable implements Runnable{ @Override public void run() { for(int i=0;i<3;i++) { System.out.println(Thread.currentThread().getName()+ "正在执行"); } } public static void main (String args[]) throws InterruptedException { Thread t = new Thread(new JoinRunnable()); t.start(); t.join(); System.out.println("子线程执行完毕"); } }
输出:
Thread-0正在执行 Thread-0正在执行 Thread-0正在执行 子线程执行完毕