网站首页 > java教程 正文
有如下两个数组,开启两个线程,分别控制一个数组,每次输出一个字符,两个线程轮流输出。
数组一:1234567
数组二:ABCDEFG
输出结果:1A2B3C4D5E6F7G
有锁实现
wait / notify
多线程编程最基本的方法,通过 wait/notify 方法进行线程间的交互,从而实现线程间轮流输出。
public class SynchronizedTest() {
public static void main(String[] args) {
char[] ai = "1234567".toCharArray();
char[] ac = "ABCDEFG".toCharArray();
Object obj = new Object();
Thread t1 = new Thread(() -> {
synchronized (obj) {
for (char c : ai) {
System.out.print(c);
try {
obj.notify(); // 唤醒其它线程
obj.wait(); // 阻塞 t1
} catch (InterruptedException e) {
e.printStackTrace();
}
}
obj.notify();
}
});
Thread t2 = new Thread(() -> {
synchronized (obj) {
for (char c : ac) {
System.out.print(c);
try {
obj.notify(); // 唤醒其它线程
obj.wait(); // 阻塞 t2
} catch (InterruptedException e) {
e.printStackTrace();
}
}
obj.notify();
}
});
t1.start();
t2.start();
}
}
LockSupport
LockSupport 是一个线程阻塞工具类,可以让线程在任意位置阻塞或者唤醒。
方法介绍:
- LockSupport.park(),阻塞当前线程
- LockSupport.park(线程名),阻塞指定线程
- LockSupport.unpark(线程名),唤醒指定线程
public class LockSupportTest {
private static Thread t1, t2;
public static void main(String[] args) {
char[] ai = "1234567".toCharArray();
char[] ac = "ABCDEFG".toCharArray();
t1 = new Thread(() -> {
for (char c : ai) {
System.out.print(c);
LockSupport.unpark(t2); // 唤醒 t2
LockSupport.park(); // 阻塞 t1
}
});
t2 = new Thread(() -> {
for (char c : ac) {
LockSupport.park(); // 阻塞 t2
System.out.print(c);
LockSupport.unpark(t1); // 唤醒 t1
}
});
t1.start();
t2.start();
}
}
无锁实现
volatile
利用 volatile 线程可见性的特性,当 displayFlag 为 true 时,第一个线程输出,为 false 时,第二个线程输出,如此反复。
public class VolatileTest {
private static volatile boolean displayFlag = true;
public static void main(String[] args) {
char[] ai = "1234567".toCharArray();
char[] ac = "ABCDEFG".toCharArray();
Thread t1 = new Thread(() -> {
for (char c : ai) {
while (!displayFlag) {
}
System.out.print(c);
displayFlag = false;
}
});
Thread t2 = new Thread(() -> {
for (char c : ac) {
while (displayFlag) {
}
System.out.print(c);
displayFlag = true;
}
});
t1.start();
t2.start();
}
}
Atomic 原子类
利用原子类中的方法具备原子性的特性
public class AtomicTest {
private static AtomicInteger atomicFlag = new AtomicInteger(0);
public static void main(String[] args) {
char[] ai = "1234567".toCharArray();
char[] ac = "ABCDEFG".toCharArray();
Thread t1 = new Thread(() -> {
for (char c : ai) {
while (atomicFlag.get() == 1) {
}
System.out.print(c);
atomicFlag.set(1);
}
});
Thread t2 = new Thread(() -> {
for (char c : ac) {
while (atomicFlag.get() == 0) {
}
System.out.print(c);
atomicFlag.set(0);
}
});
t1.start();
t2.start();
}
}
方法其实还有很多,有兴趣的同学可以自己动手,并在文章下面回复,共同学习。
接下来会陆续推出 JAVA并发编程、数据库、JVM、Spring、SpringBoot、SpringCloud的用法及源码分析,有兴趣的可以关注一下
- 上一篇: 二维数组的打印
- 下一篇: 如何在 Bash shell 脚本中打印数组
猜你喜欢
- 2024-11-21 新手初学Java数组难度大?这篇文章帮你解决
- 2024-11-21 Java-实现动态数组(ArrayList<Integer>集合)
- 2024-11-21 新手初学Java要注意什么 数组要学哪些知识点
- 2024-11-21 Java笔记二数组
- 2024-11-21 郑州Java培训学习之数组知识梳理
- 2024-11-21 从零开始学JAVA-3.超详细-方法和数组的学习
- 2024-11-21 C/C++编程笔记:如何在C++中打印数组参数大小?赶紧补课
- 2024-11-21 C语言的数组的构建与打印
- 2024-11-21 如何在 Bash shell 脚本中打印数组
- 2024-11-21 shell中如何逆序打印数组的内容,或者反转一个数组?
你 发表评论:
欢迎- 最近发表
-
- 五,网络安全IDA Pro反汇编工具初识及逆向工程解密实战
- 「JAVA8」- Lambda 表达式(java lambda表达式原理)
- 深入探讨Java代码保护:虚拟机保护技术的新时代
- Nginx反向代理原理详解(图文全面总结)
- 逆向拆解日本IT,哪些Java技术栈薪资溢价高
- mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比
- Spring Boot集成ProGuard轻松实现Java 代码混淆, Java 应用固若金汤
- 从 Java 代码逆向工程生成 UML 类图和序列图
- 人与人相处:尊重是标配,靠谱是高配,厚道是顶配
- Windows系统安装日期如何修改(windows10怎么修改安装日期)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)