✅作者简介:
全栈领域新星创作者,阿里云专家博主,退役复学在校学生
推荐学习专栏:
Spring系列
Spring Boot 系列
秋招面试题
再次渡入繁世,人潮汹涌,眼里茫然,信仰永恒,皆为华夏
目录
写给读者
初始JAVA
多线程
1、有三个线程T1,T2,T3,如何保证顺序执行?
2、SynchronizedMap和ConcurrentHashMap有什么区别?
3、什么是线程安全
总结
大家好,借着本次猿创征文活动我将分享一下自己的JAVA技术的成长之路。其实对于我来说刚开始学习JAVA还是很吃力的,之前都没有接触到计算机领域和编程相关的知识,刚回到地方的时候,是十月份这对我来说,更比其他人更晚的接触到这个编程领域,当时我身为计科的学生,学校并没有给我们安排C语言的课程,直接给我安排上了JAVA,至此我跟JAVA结下了一段孽缘。当时有两门语言让我头大,一门语言是英语,另一门语言就是JAVA,现在回想起来欲哭无泪。
当时刚学JAVA的时候,纯的跟白开水一样纯的小白什么编译器、环境变量等,对当时的我根本就是两眼摸黑,无计可施,当时没上完一个阶段就要布置一个实践报告,要我们写代码,我只能在CSDN上面搜索代码copy上去,讲实话自我感觉根本没学到什么东西。后来遇见一些有趣的人,让我觉得JAVA这门语言也并不是那么苦涩难懂,开启我的兴趣,从此我跟JAVA结下了一段孽缘。
我认为学习JAVA这么语言,多线程这个至关重要,下面是我遇见的一些线程问题,整理出来跟大家一起分享。
在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。
实际上先启动三个线程中哪一个都行, 因为在每个线程的run方法中用join方法限定了三个线程的执行顺序。
public class JoinTest2 {
// 1.现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 引用t1线程,等待t1线程执行完
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 引用t2线程,等待t2线程执行完
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t3.start();//这里三个线程的启动顺序可以任意,大家可以试下! t2.start();
t1.start();
}
}
SynchronizedMap()和Hashtable一样,实现上在调用map所有方法时,都对整个map进行同步。而ConcurrentHashMap的实现却更加精细,它对map中的所有桶加了锁。所以,只要有一个线程访问map,其他线程就无法进入map,而如果一个线程在访问ConcurrentHashMap某个桶时,其他线程,仍然可以对map执行某些操作。
所以,ConcurrentHashMap在性能以及安全性方面,明显比Collections.synchronizedMap()更加有优势。同时,同步操作精确控制到桶,这样,即使在遍历map时,如果其他线程试图对map进行数据修改,也不会抛出ConcurrentModificationException。
线程安全就是说多线程访问同一段代码,不会产生不确定的结果。
又是一个理论的问题,各式各样的答案有很多,我给出一个个人认为解释地最好的:如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么你的代码就是线程安全的。
这个问题有值得一提的地方,就是线程安全也是有几个级别的:
(1)不可变
像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用
(2)绝对线程安全
不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的
类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet
(3)相对线程安全
相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个
Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。
(4)线程非安全
这个就没什么好说的了,ArrayList、LinkedList、HashMap等都是线程非安全的类
有关我的JAVA技术成长之路分享就到此结束了,希望通过我的这篇文章能帮大家点亮JAVA技术之灯,希望有一天我们能够顶峰相见,笑看风云。