赞
踩
两者的概念:
进程:什么是进程呢?拿windows系统来说,比如qq.exe,微信等在运行的软件,就是一个独立的进程,可以打开任务管理器,查看一下自己电脑上的进程:
线程:线程是任务调度和执行的基本单位,一个进程可以包含多个线程。而线程是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
并发:在一个时间段,可能很短,多个线程可以去操作一个资源但不是真正意义上的同一时刻。
并行:在同一时间可以去操作不同的东西,就是做不同的事情。
并行需要电脑的多核支持,而并发不需要。
首先引出线程的概念:以买票的程序
public class SaleTicketDemo01 { public static void main(String[] args) { Ticket ticket = new Ticket(); /** * 开始卖票,三个各自分配,跟cpu和操作系统有关,随机调度 */ new Thread(() -> { for (int i = 0; i < 40; i++) { ticket.sale(); } }, "A").start(); new Thread(() -> { for (int i = 0; i < 40; i++) { ticket.sale(); } }, "B").start(); new Thread(() -> { for (int i = 0; i < 40; i++) { ticket.sale(); } }, "C").start(); } } /** * 资源类 */ class Ticket{ private int number = 30; /** * ReentrantLock: 可重入锁 */ Lock lock = new ReentrantLock(); public void sale() { lock.lock(); try { if (number > 0) { System.out.println(java.lang.Thread.currentThread().getName() +"\t 卖出第:" + (number--) + " \t 还剩下: " + number ); } }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } }
这里直接是使用 new Thread(); 来创建线程的,业务逻辑是。
存在30张票,分三个人进行售卖,那这个时候就有问题,会存在线程不安全的情况,比如:A不知道B卖了多少,就会存在数量不一致的情况,所以需要加上锁,这里采用的是java里面的可重入锁。就可以解决线程不安全的问题。
在java中有很多线程不安全的类,就说其中几个最常见的。
List<String> list = new ArrayList<>();
for (int i = 1; i <= 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
运行这段代码的时候会出现一个并发异常:java.util.ConcurrentModificationException,这就是因为线程不安全的原因造成的并发异常。
List<String> list = new Vector<>();
List<String> list = Collections.synchronizedList(new ArrayList<>());
List<String> list = new CopyOnWriteArrayList<>();
这三种方式都可以解决List线程不安全的情况。
private static void setNotSafe() {
Set<String> strings = new HashSet<>();
for (int i = 1; i <= 30; i++) {
new Thread(() -> {
strings.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(strings);
}, String.valueOf(i)).start();
}
}
这段程序执行结果同样会报出异常:java.util.ConcurrentModificationException。
解决方法也是和上面的List的一样,使用集合工具类和写实集合类。
private static void mapNotSafe() {
Map<String, String> map = new ConcurrentHashMap<>(16);
for (int i = 1; i <= 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}
}
当然这只是很常见的一些,且实用率较高的一些类,还有StringBuilder、SimpleDateFormat等也是不安全的类,谢谢大家的阅读,线程、并发在java中算是基础也是一个难点,大家一起努力学习,五一学习快乐!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。