【Java并发编程一】线程安全问题
1.多线程的实现
多线程有两种实现方式:
1.1.继承Thread类 =>示例:A a=new A(); a.start();
1.2.实现Runnable接口 =>示例:A a=new A(); new Thread(A,自定义线程名称).start();
其实Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式
获取当前线程名称:Thread.currentThread().getName()
调用线程是thread.start(),真正执行线程是 thread.run()
具体代码:
/**
* 继承Thread类
* @date 2019/3/29 11:19
*/
public class SimpleThread extends Thread{ @Override
public void run() {
super.run();
Thread thread = Thread.currentThread();
System.out.println("Thread =>当前执行的线程为:"+thread.getName());
}
} /**
* 实现Runnable接口
* @date 2019/3/29 11:28
*/
public class SimpleRunnable implements Runnable { @Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("Runnable =>当前执行的线程为:"+thread.getName());
}
} public class TestMain { /**执行线程示例1*/
private static void callSimpleThread(){
int index=10;
for (int i = 0; i < index; i++) {
Thread thread=new SimpleThread();
thread.start();
}
} /**执行线程示例1*/
private static void callSimpleRunnable(){
int index=10;
for (int i = 0; i < index; i++) {
SimpleRunnable simpleRunnable=new SimpleRunnable();
new Thread(simpleRunnable,"Runnable-"+i).start();
}
} public static void main(String[] args) { callSimpleThread(); callSimpleRunnable();
} }
2.多线程安全问题
2.1线程不安全示例
多线程最容易产生的一个问题就是线程安全问题,下面使用一个卖票的例子来体现。
场景描述:现在有两个售票员,一共卖10张车票
public class SellTicket extends Thread {
private static int NUMBER = 10;
public SellTicket(String name) {
super(name);
}
@Override
public void run() {
String s = "线程:" + Thread.currentThread().getName();
while (NUMBER > 0) {
int i = NUMBER--;
System.out.println(s + " => 卖了第" + i + "号票");
}
System.out.println(s + ",票已经卖完");
super.run();
}
public static void main(String[] args) {
SellTicket thread1 = new SellTicket("售票员A");
thread1.start();
SellTicket thread2 = new SellTicket("售票员B");
thread2.start();
}
}
执行结果如下:
我们发现售票员A 和售票员B都卖了10号票,这就是线程不安全导致的结果

2.2线程不安全解决方法
方案一:使用同步代码解决
格式:synchronized(锁对象){需要被同步的代码}
锁对象可以为this锁,也可以自定义对象锁 方案二:使用同步函数解决
同步函数就是使用synchronized修饰一个函数
下面采用同步代码块解决
public class SafetySellTicket extends Thread {
private static int NUMBER = 10;
@Override
public void run() {
String s = "线程:" + Thread.currentThread().getName();
while (NUMBER > 0) {
synchronized (this) {
if (NUMBER > 0) {
int i = NUMBER--;
System.out.println(s + " => 卖了第" + i + "号票");
} else {
System.out.println(s + ",票已经卖完");
break;
}
}
}
super.run();
}
public static void main(String[] args) {
SafetySellTicket thread1 = new SafetySellTicket();
thread1.start();
SafetySellTicket thread2 = new SafetySellTicket();
thread2.start();
}
}
【Java并发编程一】线程安全问题的更多相关文章
- Java并发编程基础-线程安全问题及JMM(volatile)
什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程控制
在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...
- Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- (转)Java并发编程:线程池的使用
背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...
- Java并发编程:线程池的使用(转载)
转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- Java并发编程:线程池的使用(转载)
文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- [转]Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
随机推荐
- java 中使用RSA非对称性加密解密
需要引入的jar包:bcprov-jdk15on-161.jar 下载地址:https://www.bouncycastle.org/latest_releases.html //公钥加密 publi ...
- 代理模式-JDK Proxy(Java实现)
代理模式-JDK Proxy 使用JDK支持的代理模式, 动态代理 场景如下: 本文例子代理了ArrayList, 在ArrayList每次操作时, 在操作之前和之后都进行一些额外的操作. Array ...
- jQuery使用():Deferred有状态的回调列表(含源码)
deferred的功能及其使用 deferred的实现原理及模拟源码 一.deferred的功能及其使用 deferred的底层是基于callbacks实现的,建议再熟悉callbacks的内部机制前 ...
- J.U.C-三剑客[semaphore\CyclicBarrier\CountDownLatch]
一.semaphore信号量,底层也是基于AQS 使用: /** * 可以理解为控制某个资源最多有多少个线程同时执行,(比如洗手间,并行与排队) * 如果满了只能等待直到其它资源释放(可以理解为并发量 ...
- echo 输入背景和字体常用方法
ECHO输出背景颜色以及文字颜色输出格式: echo -e "\033[字背景颜色;文字颜色m字符串\033[0m"例如: echo -e & ...
- java 格式化字符串
Date 格式转化为字符串 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); java.util.Date date ...
- css实现背景模糊,但不影响背景上的内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Ubuntu 18.04 记录
登录后死机,关机时死机的解决方法 更新内核并安装 Nvidia 显卡驱动可解决. 在内核更新为 4.15.18,Nvidia 显卡驱动为 390 时,问题解决. 使用 LiveCD 启动,然后 mou ...
- python3: 自动化测试框架pytest
最近在学习web自动化,所以在这里总结一下pytest框架. 其实pytest 和 unittest 都是自动化测试框架,但是pytest更好用一些,有以下几个优点:1)可以根据标签执行用例:2)?? ...
- 第十七节,OpenCV(学习六)图像轮廓检测
1.检测轮廓 轮廓检测是图像处理中经常用到的,OpenCV-Python接口中使用cv2.findContours()函数查找检测物体的轮廓. cv2.findContours(image, mode ...