多線程是Java實現多任務的基礎:java
Thread對象表明一個線程:調用Tread.currentThread()獲取當前線程。
多任務程序一般須要針對每一個任務啓動一個新的線程,來處理這個用戶的請求,也能夠從線程池取出一個空閒的線程來處理。
如何在一個線程內傳遞狀態:
例如咱們在一個線程處理過程當中,常常須要調用不一樣的類來處理不一樣的功能,咱們如何在這些方法中可以方便的獲取到當前的用戶?
JDK提供了ThreadLocal在一個線程中傳遞同一個對象多線程
static ThreadLocal<String> threadLocalUser = new ThreadLocal<>(); threadLocalUser.set("Bob"); //給當前線程綁定一個指定的值 ... String current = threadLocalUser.get(); //調用get()方法能夠在當前線程隨時獲取到已綁定的這個值 String current = threadLocalUser.get(); String current = threadLocalUser.get(); ... threadLocalUser.remove(); //把綁定的值從當前線程中解除
ThreadLocal典型的使用方式:
ThreadLocal必定要在finally中清除。當前線程執行完相關代碼之後,頗有可能從新放入線程池中,若是ThreadLocal沒有被清除,這個線程在執行其餘代碼的時候,就會把上一次的狀態帶進去。this
try{ UserContext.set(user); ... }finally{ UserContext.remove(); }
class User{ //表示當前的一個用戶 String name; int level; public User(String name, int level){ this.name = name; this.level = level; } } class UserContext implements AutoCloseable{ static final ThreadLocal<User> context = new ThreadLocal<>(); //全局惟一靜態變量 public static User getCurrentUser(){ //獲取當前線程的ThreadLocal User return context.get(); } public UserContext(User user){ //初始化ThreadLocal的User context.set(user); } public void close(){ //移除ThreadLocal關聯的User context.remove(); } } class ProcessThread extends Thread{ User user; ProcessThread(User user){ //傳入User對象 this.user = user; } public void run(){ try(UserContext ctx = new UserContext(user)){ new Greeting().hello(); Level.checkLevel(); } } } class Greeting{ void hello(){ User user = UserContext.getCurrentUser(); System.out.println("Hello,"+user.name+"!"); } } class Level{ static void checkLevel(){ User user = UserContext.getCurrentUser(); if(user.level>100){ System.out.println(user.name+" is a VIP user."); }else{ System.out.println(user.name+" is a registered user."); } } } public class Main{ public static void main(String[] args) throws Exception{ Thread t1 = new ProcessThread(new User("Bob",120)); Thread t2 = new ProcessThread(new User("Alice",80)); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("Main end"); } }
能夠把ThreadLocal當作全局Map<Thread, Object>:線程
Object ThreadLocalValue = threadLocalMap.get(Thread.currentThread());