使用ThreadLocal可以使对象达到线程隔离的目的。为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。
构造方法:ThreadLocal():创建一个线程本地变量
protected T initialValue():返回此线程局部变量的当前线程的初始值。最多在每次访问线程来获得每个线程局部变量时调用此方法一次,即线程第一次使用 get() 方法访问变量的时候。如果线程先于 get 方法调用 set(T) 方法,则不会在线程中再调用 initialValue 方法。
T get():
void set(T value):将此线程局部变量的当前线程副本中的值设置为指定值。许多应用程序不需要这项功能,它们只依赖于 initialValue() 方法来设置线程局部变量的值。
void remove():移除此线程局部变量的值。这可能有助于减少线程局部变量的存储需求。如果再次访问此线程局部变量,那么在默认情况下它将拥有其 initialValue。
在程序中一般都重写initialValue方法,以给定一个特定的初始值。
注意ThreadLocal对象在那里构造就属于那个线程。不可以跨越线程调用ThreadLocal对象
注意所有线程使用完毕ThreadLocal中包含的对象的时候,需要重置对象的属性。因为ThreadLocal实现的方法并不是克隆或者拷贝。
Boss.java
package com.hzj163.myhandler;
import java.util.ArrayList;
//副本BOSS
public class Boss {
//boss名称
String name;
//boss掉落装备
ArrayList<String> equipment;
//是否死亡
boolean dead;
public boolean isDead() {
return dead;
}
public void setDead(boolean dead) {
this.dead = dead;
}
public Boss() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<String> getEquipment() {
return equipment;
}
public void setEquipment(ArrayList<String> equipment) {
this.equipment = equipment;
}
}
WOWHFB.java
package com.hzj163.myhandler;
import java.util.ArrayList;
//魔兽世界英雄副本
public class WOWHFB {
//副本名称
String name;
//BOSS列表
ArrayList<Boss> bosses;
public WOWHFB(String name, ArrayList<Boss> bosses) {
this.name = name;
this.bosses = bosses;
}
public WOWHFB() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<Boss> getBosses() {
return bosses;
}
public void setBosses(ArrayList<Boss> bosses) {
this.bosses = bosses;
}
}
OtherActivity.java
package com.hzj163.myhandler;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
//这里为了演示ThreadLocal,所以不做任何封装
public class OtherActivity extends AppCompatActivity {
//副本对象
WOWHFB wowhfb;
TextView textView1;
TextView textView2;
TextView textView3;
Handler handlerMain = new Handler();
Button button1;
//管理线程
HashSet hashSet;
//同步锁
Object object = new Object();
//初始化副本
public WOWHFB initWowhfb() {
//实例化副本对象【准备让3个队伍同时进入副本砍BOSS】
WOWHFB wowhfb = new WOWHFB();
wowhfb.setName("黑石塔上层");
//设置boss
Boss boss1 = new Boss();
//boss名称
boss1.setName("督军扎伊拉");
//掉落装备
ArrayList<String> equipment1 = new ArrayList();
equipment1.add("沙赫拉姆荒芜之剑");
equipment1.add("魔能军刺");
equipment1.add("烬鳞护符");
equipment1.add("奥秘兜帽");
equipment1.add("霜染兜帽");
equipment1.add("流光兜帽");
equipment1.add("缚光者面罩");
//设置装备
boss1.setEquipment(equipment1);
//设置boss是否死亡
boss1.setDead(false);
Boss boss2 = new Boss();
boss2.setName("狂野的怒翼");
ArrayList<String> equipment2 = new ArrayList();
equipment2.add("黑手的毁灭战戟");
equipment2.add("怒翼的火焰之牙");
equipment2.add("鼓风项圈");
equipment2.add("火刃项圈");
equipment2.add("颅齿项链");
equipment2.add("风印项链");
equipment2.add("魔导师之链");
boss2.setEquipment(equipment2);
boss2.setDead(false);
Boss boss3 = new Boss();
boss3.setName("指挥官萨贝克");
ArrayList<String> equipment3 = new ArrayList();
equipment3.add("萨贝克的邪恶长剑");
equipment3.add("萨贝克的野蛮长剑");
equipment3.add("萨贝克的幸运石");
equipment3.add("奥秘手套");
equipment3.add("霜染手套");
equipment3.add("流光手套");
equipment3.add("缚光者手套");
boss3.setEquipment(equipment3);
boss3.setDead(false);
Boss boss4 = new Boss();
boss4.setName("奇拉克");
ArrayList<String> equipment4 = new ArrayList();
equipment4.add("芬克的解剖刀");
equipment4.add("奇拉克的邪血药水");
equipment4.add("罗杰的棕色金刚石印戒");
equipment4.add("赛德的协鸣指环");
equipment4.add("血棘指环");
boss4.setEquipment(equipment4);
boss4.setDead(false);
Boss boss5 = new Boss();
boss5.setName("折铁者高尔山");
ArrayList<String> equipment5 = new ArrayList();
equipment5.add("石化重锤");
equipment5.add("联刃斗篷");
equipment5.add("神射大氅");
equipment5.add("暴力和谐斗篷");
equipment5.add("邪骨斗篷");
equipment5.add("秘法斗篷");
boss5.setEquipment(equipment5);
boss5.setDead(false);
//实例化BOSS集合
ArrayList<Boss> bosses = new ArrayList();
bosses.add(boss1);
bosses.add(boss2);
bosses.add(boss3);
bosses.add(boss4);
bosses.add(boss5);
//设置Boss集合
wowhfb.setBosses(bosses);
return wowhfb;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
getSupportActionBar().setTitle("黑石塔上层");
textView1 = (TextView) findViewById(R.id.textView1);
textView2 = (TextView) findViewById(R.id.textView2);
textView3 = (TextView) findViewById(R.id.textView3);
button1 = (Button) findViewById(R.id.button1);
//负责监听所有线程结束
hashSet = new HashSet();
//实例化副本对象
wowhfb = initWowhfb();
}
//线程1
Runnable runnable1 = new Runnable() {
@Override
public void run() {
//添加集合管理线程【需要同步,以为是多个线程共享一个集合】
synchronized (object) {
hashSet.add(this);
}
//开始副本,使用ThreadLocal隔离WOWHFB对象
ThreadLocal<WOWHFB> threadLocal = new ThreadLocal() {
//初始化副本
@Override
protected Object initialValue() {
return wowhfb;
}
};
//战斗中......
handlerMain.post(new Runnable() {
@Override
public void run() {
textView1.setText("战队1开始战斗");
}
});
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//战斗结束【使用threadLocal.get()拿出副本对象】
WOWHFB temp = threadLocal.get();
//杀死了两个boss
temp.getBosses().get(0).setDead(true);
temp.getBosses().get(1).setDead(true);
//战利品
ArrayList<String> result = new ArrayList();
//获取装备
Random random = new Random();
//随机获取装备
int randomTemp1 = random.nextInt(temp.getBosses().get(0).getEquipment().size());
int randomTemp2 = random.nextInt(temp.getBosses().get(1).getEquipment().size());
result.add(temp.getBosses().get(0).getEquipment().get(randomTemp1));
result.add(temp.getBosses().get(1).getEquipment().get(randomTemp2));
//收集信息
final StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("***战队1杀死的BOSS***");
stringBuffer.append("\r\n");
for (int i = 0; i < temp.getBosses().size(); i++) {
if (temp.getBosses().get(i).isDead()) {
stringBuffer.append(temp.getBosses().get(i).getName());
stringBuffer.append("\r\n");
}
}
stringBuffer.append("***战利品***");
stringBuffer.append("\r\n");
for (int i = 0; i < result.size(); i++) {
stringBuffer.append(result.get(i));
stringBuffer.append("\r\n");
}
//添加集合管理线程【需要同步,以为是多个线程共享一个集合】
synchronized (object) {
hashSet.remove(this);
}
//显示战利品
handlerMain.post(new Runnable() {
@Override
public void run() {
textView1.setText(stringBuffer.toString());
//判断是否所有线程结束
if (hashSet.isEmpty()) {
button1.setEnabled(true);
//这里要注意的是ThreadLocal对象并没有克隆方案克隆出多个副本对象
//副本对象其实依然是一个,所以所有线程结束后,需要重置副本对象
wowhfb = initWowhfb();
}
}
});
}
};
//线程2
Runnable runnable2 = new Runnable() {
@Override
public void run() {
synchronized (object) {
hashSet.add(this);
}
//开始副本,使用ThreadLocal隔离WOWHFB对象
ThreadLocal<WOWHFB> threadLocal = new ThreadLocal() {
//初始化副本
@Override
protected Object initialValue() {
return wowhfb;
}
};
handlerMain.post(new Runnable() {
@Override
public void run() {
textView2.setText("战队2开始战斗");
}
});
//战斗中......
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//战斗结束
WOWHFB temp = threadLocal.get();
//杀死了两个boss
temp.getBosses().get(0).setDead(true);
//战利品
ArrayList<String> result = new ArrayList();
//获取装备
Random random = new Random();
//随机获取装备
int randomTemp1 = random.nextInt(temp.getBosses().get(0).getEquipment().size());
result.add(temp.getBosses().get(0).getEquipment().get(randomTemp1));
//收集信息
final StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("***战队2杀死的BOSS***");
stringBuffer.append("\r\n");
for (int i = 0; i < temp.getBosses().size(); i++) {
if (temp.getBosses().get(i).isDead()) {
stringBuffer.append(temp.getBosses().get(i).getName());
stringBuffer.append("\r\n");
}
}
stringBuffer.append("***战利品***");
stringBuffer.append("\r\n");
for (int i = 0; i < result.size(); i++) {
stringBuffer.append(result.get(i));
stringBuffer.append("\r\n");
}
synchronized (object) {
hashSet.remove(this);
}
//显示战利品
handlerMain.post(new Runnable() {
@Override
public void run() {
textView2.setText(stringBuffer.toString());
//判断是否所有线程结束
if (hashSet.isEmpty()) {
button1.setEnabled(true);
wowhfb = initWowhfb();
}
}
});
}
};
//线程3
Runnable runnable3 = new Runnable() {
@Override
public void run() {
synchronized (object) {
hashSet.add(this);
}
//开始副本,使用ThreadLocal隔离WOWHFB对象
ThreadLocal<WOWHFB> threadLocal = new ThreadLocal() {
//初始化副本
@Override
protected Object initialValue() {
return wowhfb;
}
};
handlerMain.post(new Runnable() {
@Override
public void run() {
textView3.setText("战队3开始战斗");
}
});
//战斗中......
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//战斗结束
WOWHFB temp = threadLocal.get();
//杀死了两个boss
temp.getBosses().get(0).setDead(true);
temp.getBosses().get(1).setDead(true);
temp.getBosses().get(2).setDead(true);
temp.getBosses().get(3).setDead(true);
temp.getBosses().get(4).setDead(true);
//战利品
ArrayList<String> result = new ArrayList();
//获取装备
Random random = new Random();
//随机获取装备
int randomTemp1 = random.nextInt(temp.getBosses().get(0).getEquipment().size());
int randomTemp2 = random.nextInt(temp.getBosses().get(1).getEquipment().size());
int randomTemp3 = random.nextInt(temp.getBosses().get(2).getEquipment().size());
int randomTemp4 = random.nextInt(temp.getBosses().get(3).getEquipment().size());
int randomTemp5 = random.nextInt(temp.getBosses().get(4).getEquipment().size());
result.add(temp.getBosses().get(0).getEquipment().get(randomTemp1));
result.add(temp.getBosses().get(1).getEquipment().get(randomTemp2));
result.add(temp.getBosses().get(2).getEquipment().get(randomTemp3));
result.add(temp.getBosses().get(3).getEquipment().get(randomTemp4));
result.add(temp.getBosses().get(4).getEquipment().get(randomTemp5));
//收集信息
final StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("***战队3杀死的BOSS***");
stringBuffer.append("\r\n");
for (int i = 0; i < temp.getBosses().size(); i++) {
if (temp.getBosses().get(i).isDead()) {
stringBuffer.append(temp.getBosses().get(i).getName());
stringBuffer.append("\r\n");
}
}
stringBuffer.append("***战利品***");
stringBuffer.append("\r\n");
for (int i = 0; i < result.size(); i++) {
stringBuffer.append(result.get(i));
stringBuffer.append("\r\n");
}
synchronized (object) {
hashSet.remove(this);
}
//显示战利品
handlerMain.post(new Runnable() {
@Override
public void run() {
textView3.setText(stringBuffer.toString());
//判断是否所有线程结束
if (hashSet.isEmpty()) {
button1.setEnabled(true);
wowhfb = initWowhfb();
}
}
});
}
};
public void btn1(View view) {
new Thread(runnable1).start();
new Thread(runnable2).start();
new Thread(runnable3).start();
button1.setEnabled(false);
}
}
package com.hzj163.myhandler;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Switch;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
//封装版本
public class OtherActivity1 extends AppCompatActivity {
//1战队开始
public static final int START_1 = 1;
//2战队开始
public static final int START_2 = 2;
//3战队开始
public static final int START_3 = 3;
//1战队结束
public static final int END_1 = 4;
//2战队结束
public static final int END_2 = 5;
//3战队结束
public static final int END_3 = 6;
//副本对象
WOWHFB wowhfb;
TextView textView1;
TextView textView2;
TextView textView3;
Button button1;
//管理线程
HashSet hashSet;
//同步锁
Object object = new Object();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
getSupportActionBar().setTitle("黑石塔上层");
textView1 = (TextView) findViewById(R.id.textView1);
textView2 = (TextView) findViewById(R.id.textView2);
textView3 = (TextView) findViewById(R.id.textView3);
button1 = (Button) findViewById(R.id.button1);
//负责监听所有线程结束
hashSet = new HashSet();
wowhfb = initWowhfb();
}
//主线程handler
MyHandler handlerMain = new MyHandler(new WeakReference<OtherActivity1>(OtherActivity1.this));
static class MyHandler extends Handler {
WeakReference<OtherActivity1> weakReference;
public MyHandler(WeakReference<OtherActivity1> weakReference) {
this.weakReference = weakReference;
}
@Override
public void handleMessage(Message msg) {
OtherActivity1 temp = weakReference.get();
switch (msg.what) {
case START_1:
temp.textView1.setText("战队1开始战斗");
break;
case START_2:
temp.textView2.setText("战队2开始战斗");
break;
case START_3:
temp.textView3.setText("战队3开始战斗");
break;
case END_1:
temp.textView1.setText(msg.obj.toString());
temp.reFB();
break;
case END_2:
temp.textView2.setText(msg.obj.toString());
temp.reFB();
break;
case END_3:
temp.textView3.setText(msg.obj.toString());
temp.reFB();
break;
}
}
}
//初始化副本
public WOWHFB initWowhfb() {
//实例化副本对象【准备让3个队伍同时进入副本砍BOSS】
WOWHFB wowhfb = new WOWHFB();
wowhfb.setName("黑石塔上层");
//设置boss
Boss boss1 = new Boss();
//boss名称
boss1.setName("督军扎伊拉");
//掉落装备
ArrayList<String> equipment1 = new ArrayList();
equipment1.add("沙赫拉姆荒芜之剑");
equipment1.add("魔能军刺");
equipment1.add("烬鳞护符");
equipment1.add("奥秘兜帽");
equipment1.add("霜染兜帽");
equipment1.add("流光兜帽");
equipment1.add("缚光者面罩");
//设置装备
boss1.setEquipment(equipment1);
//设置boss是否死亡
boss1.setDead(false);
Boss boss2 = new Boss();
boss2.setName("狂野的怒翼");
ArrayList<String> equipment2 = new ArrayList();
equipment2.add("黑手的毁灭战戟");
equipment2.add("怒翼的火焰之牙");
equipment2.add("鼓风项圈");
equipment2.add("火刃项圈");
equipment2.add("颅齿项链");
equipment2.add("风印项链");
equipment2.add("魔导师之链");
boss2.setEquipment(equipment2);
boss2.setDead(false);
Boss boss3 = new Boss();
boss3.setName("指挥官萨贝克");
ArrayList<String> equipment3 = new ArrayList();
equipment3.add("萨贝克的邪恶长剑");
equipment3.add("萨贝克的野蛮长剑");
equipment3.add("萨贝克的幸运石");
equipment3.add("奥秘手套");
equipment3.add("霜染手套");
equipment3.add("流光手套");
equipment3.add("缚光者手套");
boss3.setEquipment(equipment3);
boss3.setDead(false);
Boss boss4 = new Boss();
boss4.setName("奇拉克");
ArrayList<String> equipment4 = new ArrayList();
equipment4.add("芬克的解剖刀");
equipment4.add("奇拉克的邪血药水");
equipment4.add("罗杰的棕色金刚石印戒");
equipment4.add("赛德的协鸣指环");
equipment4.add("血棘指环");
boss4.setEquipment(equipment4);
boss4.setDead(false);
Boss boss5 = new Boss();
boss5.setName("折铁者高尔山");
ArrayList<String> equipment5 = new ArrayList();
equipment5.add("石化重锤");
equipment5.add("联刃斗篷");
equipment5.add("神射大氅");
equipment5.add("暴力和谐斗篷");
equipment5.add("邪骨斗篷");
equipment5.add("秘法斗篷");
boss5.setEquipment(equipment5);
boss5.setDead(false);
//实例化BOSS集合
ArrayList<Boss> bosses = new ArrayList();
bosses.add(boss1);
bosses.add(boss2);
bosses.add(boss3);
bosses.add(boss4);
bosses.add(boss5);
//设置Boss集合
wowhfb.setBosses(bosses);
return wowhfb;
}
//战斗流程
public void startFB(int massageStartWhat, int massageEndWhat, int sleep) {
//随机数准备
Random random = new Random();
//添加集合管理线程【需要同步,以为是多个线程共享一个集合】
synchronized (object) {
hashSet.add(this);
}
//开始副本,使用ThreadLocal隔离WOWHFB对象
ThreadLocal<WOWHFB> threadLocal = new ThreadLocal() {
//初始化副本
@Override
protected Object initialValue() {
return wowhfb;
}
};
//发送战斗中......消息
Message messageStart = handlerMain.obtainMessage();
messageStart.what = massageStartWhat;
messageStart.sendToTarget();
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
//战斗结束【使用threadLocal.get()拿出副本对象】
WOWHFB temp = threadLocal.get();
//杀死了N个boss【随机】
int bossDead = random.nextInt(temp.getBosses().size() - 1);
bossDead++;
//战利品
ArrayList<String> result = new ArrayList();
for (int i = 0; i < bossDead; i++) {
temp.getBosses().get(i).setDead(true);
//随机获取装备
int randomTempIndex = random.nextInt(temp.getBosses().get(i).getEquipment().size());
result.add(temp.getBosses().get(i).getEquipment().get(randomTempIndex));
}
//收集信息
final StringBuffer stringBuffer = new StringBuffer();
//判断战队
switch (massageStartWhat) {
case START_1:
stringBuffer.append("***战队1杀死的BOSS***");
break;
case START_2:
stringBuffer.append("***战队2杀死的BOSS***");
break;
case START_3:
stringBuffer.append("***战队3杀死的BOSS***");
break;
}
stringBuffer.append("\r\n");
//收集杀死的Boss名称
for (int i = 0; i < temp.getBosses().size(); i++) {
if (temp.getBosses().get(i).isDead()) {
stringBuffer.append(temp.getBosses().get(i).getName());
stringBuffer.append("\r\n");
}
}
//收集杀死的Boss的装备
stringBuffer.append("***战利品***");
stringBuffer.append("\r\n");
for (int i = 0; i < result.size(); i++) {
stringBuffer.append(result.get(i));
stringBuffer.append("\r\n");
}
//添加集合管理线程【需要同步,以为是多个线程共享一个集合】
synchronized (object) {
hashSet.remove(this);
}
//发送战斗结束消息
Message messageEnd = handlerMain.obtainMessage();
messageEnd.what = massageEndWhat;
messageEnd.obj = stringBuffer;
messageEnd.sendToTarget();
}
//重置副本
public void reFB() {
//判断是否所有线程结束
if (hashSet.isEmpty()) {
button1.setEnabled(true);
//这里要注意的是ThreadLocal对象并没有克隆方案克隆出多个副本对象
//副本对象其实依然是一个,所以所有线程结束后,需要重置副本对象
wowhfb = initWowhfb();
}
}
//战队1
Runnable runnable1 = new Runnable() {
@Override
public void run() {
startFB(START_1, END_1, new Random().nextInt(5000) + 8000);
}
};
//战队2
Runnable runnable2 = new Runnable() {
@Override
public void run() {
startFB(START_2, END_2, new Random().nextInt(5000) + 8000);
}
};
//战队3
Runnable runnable3 = new Runnable() {
@Override
public void run() {
startFB(START_3, END_3, new Random().nextInt(5000) + 8000);
}
};
public void btn1(View view) {
//开始
new Thread(runnable1).start();
new Thread(runnable2).start();
new Thread(runnable3).start();
button1.setEnabled(false);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_other_activity1, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}