ThreadLocal
每个线程都有自己的工作内存,使用ThreadLocal类创建工作内存中的变量,不同线程访问同一个Threadlocal对象时,获取到的数据是存储在工作内存上的数据
public static void main(String[] args) throws InterruptedException {
ThreadLocal<String> local = new ThreadLocal<>(); //注意这是一个泛型类,存储类型为我们要存放的变量类型
Thread t1 = new Thread(() -> {
local.set("lbwnb"); //将变量的值给予ThreadLocal
System.out.println("变量值已设定!");
System.out.println(local.get()); //尝试获取ThreadLocal中存放的变量
});
Thread t2 = new Thread(() -> {
System.out.println(local.get()); //尝试获取ThreadLocal中存放的变量
});
t1.start();
Thread.sleep(3000); //间隔三秒
t2.start();
}
上面的代码中t1
访问local
存放的变量为t1
线程中设置的“lbwnb”,但是t2并没有在线程中设置local
的变量值,所以在访问local
存放的值时返回的null
在线程中创建子进程,无法获得父进程工作内存中的变量:
public static void main(String[] args) {
ThreadLocal<String> local = new ThreadLocal<>();
Thread t = new Thread(() -> {
local.set("lbwnb");
new Thread(() -> {
System.out.println(local.get());
}).start();
});
t.start();
}
使用inheritableThreadLocal来解决
public static void main(String[] args) {
ThreadLocal<String> local = new InheritableThreadLocal<>();
Thread t = new Thread(() -> {
local.set("lbwnb");
new Thread(() -> {
System.out.println(local.get());
}).start();
});
t.start();
}
定时器
public static void main(String[] args) {
Timer timer = new Timer(); //创建定时器对象
timer.schedule(new TimerTask() { //注意这个是一个抽象类,不是接口,无法使用lambda表达式简化,只能使用匿名内部类
@Override
public void run() {
System.out.println(Thread.currentThread().getName()); //打印当前线程名称
}
}, 1000); //执行一个延时任务
}
使用Timer创建定时任务,任务虽然执行完成了,但是我们的程序并没有停止,因为Timer内存维护了一个任务队列和一个工作线程,TimerThread继承自Thread,是一个新创建的线程,在构造时自动启动,而它的run方法会循环的读取队列中是否还有任务,如果有任务依次执行,没有的话就暂时处于休眠状态。如果要让程序自动关闭,我们可以调用Timer的cancel()
方法以正常退出程序
守护线程
在主线程中创建一个子线程,通过测试可以发现主线程已经结束但是子线程依旧在执行,而守护线程会当所有的非守护线程结束后,自动结束,也就是说,java中所有的线程都执行完毕后,守护线程会自动结束,因此守护线程不适合进行IO操作
public static void main(String[] args) throws InterruptedException{
Thread t = new Thread(() -> {
while (true){
try {
System.out.println("程序正常运行中...");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.setDaemon(true); //设置为守护线程(必须在开始之前,中途是不允许转换的)
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
}
}
注意:在守护线程中创建新的线程也是守护的