日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java多线程】高级主题:定时调度、quartz、指令重排、volatile、ThreadLocal

發布時間:2024/2/28 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java多线程】高级主题:定时调度、quartz、指令重排、volatile、ThreadLocal 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

定時調度

1000ms后執行 每隔500ms執行一次

package cn.hanquan.test;import java.util.Timer; import java.util.TimerTask;/** 定時執行*/ public class MyTimer {public static void main(String[] args) {Timer t = new Timer();t.schedule(new MyTask(), 1000, 500);// 1000ms后執行 每隔500ms執行一次} }class MyTask extends TimerTask {@Overridepublic void run() {System.out.println("大腦放松一下,打印一個hello");} }

進階:使用Quartz

官方文檔給了很多examples,想實現什么功能,可以直接復制examples里的代碼,加以修改。


指令重排

指令重排對多線程是有影響的



sxt Java 300級說這個代碼會發生指令重排,但是我測試沒有發生重排…

package cn.hanquan.test;import java.util.Timer; import java.util.TimerTask;/** 指令重排*/ public class HappenBefore {public static int a = 0;public static boolean flag = false;public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 5000; i++) {Thread t1 = new Thread(() -> {a = 1;flag = true;});Thread t2 = new Thread(() -> {if (flag) {a *= 1;// a不變}if (a == 0) {System.out.println("a=" + a);}});t1.start();t2.start();t1.join();t2.join();}} }

volatile

  • volatile用來保證數據的同步,也就是可見性

使用volatile可以讓工作內存實時保證最新,保證了同步的數據可見。有一種說法:volatile是輕量級的synchronized,比synchronized占用的資源少,同時也可以避免指令重排

未使用 Volatile

運行之后一直不結束,cpu沒有時間同步內存中的值

package cn.hanquan.test;/** 指令重排*/ public class VolatileTest {public static int num = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {while (num == 0) {}}).start();Thread.sleep(500);num = 1;} }


使用 Volatile

程序可以正常結束

package cn.hanquan.test;/** 指令重排*/ public class VolatileTest {public volatile static int num = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {while (num == 0) {}}).start();Thread.sleep(500);num = 1;} }


ThreadLocal

ThreadLocal每個線程有自己的存儲區域。自身的數據被修改時,不會影響其他的線程

代碼

例1

package cn.hanquan.test;/** 每個線程有自己的存儲區域。自身的數據被修改時,不會影響其他的線程*/ public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 5);public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(-100);System.out.println(Thread.currentThread().getName() + "后來->" + threadLocal.get());new Thread(() -> {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(2);System.out.println(Thread.currentThread().getName() + "后來->" + threadLocal.get());}).start();} } main初始->5 main后來->-100 Thread-0初始->5 Thread-0后來->2

例2

需要注意threadLocal.get()的上下文,確定其代表的是哪一個線程

package cn.hanquan.test;/** 每個線程有自己的存儲區域。自身的數據被修改時,不會影響其他的線程*/ public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 5);public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(-100);System.out.println(Thread.currentThread().getName() + "后來->" + threadLocal.get());for (int i = 0; i < 5; i++) {new Thread(new myRun()).start();}}public static class myRun implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "初始為->" + threadLocal.get());threadLocal.set(threadLocal.get() - 2);System.out.println(Thread.currentThread().getName() + "后來->" + threadLocal.get());}} } main初始->5 main后來->-100 Thread-0初始為->5 Thread-1初始為->5 Thread-0后來->3 Thread-2初始為->5 Thread-1后來->3 Thread-2后來->3 Thread-3初始為->5 Thread-3后來->3 Thread-4初始為->5 Thread-4后來->3

我的理解是:每一個Thread線程都有一個自己的獨立threadLocal,可以更改其中的數據的時候,保證其他線程的threadLocal數據不會被修改。但是這有什么意義嗎…不知道哪里能用得到?

InheritableThreadLocal

  • 可以繼承的ThreadLocal

InheritableThreadLocal繼承上下文環境的數據,復制一份給子線程(而非共享),相當于線程自己的局部變量

(1)不繼承代碼示例

package cn.hanquan.test;/** 不繼承*/ public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 5);public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(-100);System.out.println(Thread.currentThread().getName() + "后來->" + threadLocal.get());new Thread(() -> {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());}).start();} }

(2)繼承代碼示例

package cn.hanquan.test;/** InheritableThreadLocal繼承上下文環境的數據,復制一份給子線程*/ public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(20);System.out.println(Thread.currentThread().getName() + "后來->" + threadLocal.get());new Thread(() -> {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());}).start();} } main初始->null main后來->20 Thread-0初始->20

CAS

CAS是樂觀鎖的一種實現:比較并交換

先和原來的值比較。如果原來的值沒動過,則交換。如果原來的值被改動過,交換失敗。返回false。

效率高,是硬件級別的操作。也可以做到數據的共享。

Atomic原子性的操作都是使用可CAS的思想。

示例代碼

總結

以上是生活随笔為你收集整理的【Java多线程】高级主题:定时调度、quartz、指令重排、volatile、ThreadLocal的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。