【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并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
随机推荐
- mysql删除多个重复数据,多个字段添加唯一性索引
需求:删除station_id.ab_data_time.item_code_id.data_cycle.ab_value 字段重复的记录 #查询重复的数据 select b.id,b.station ...
- 半导体知识讲解:IC基础知识及制造工艺流程
本文转载自微信公众号 - 中国半导体论坛 , 链接 https://mp.weixin.qq.com/s/VhCsVGyEDrgc2XJ0jxLvaA
- vuex概念详解
阅读vuex官网以后用自己的话概括起来就是:vuex是vue配套的公共数据管理工具,它可以把一些共享的数据,保存到vuex中,方便整个程序中的任何组件直接获取或修改我们的公共数据. vuex是为了保存 ...
- jQuery中哪几种选择器
基本选择器:直接根据id,css类名,元素名返回dom元素: 层次选择器:也叫路径选择器: $("div span") 选取<div>里的所有<span>元 ...
- setLocale(java.util.Locale), setCharacterEncoding(java.lang.String),setContentType(java.lang.String type)
对于setCharacterEncoding(java.lang.String),这个方法是javax.servlet.ServletRequest和javax.servlet.ServletResp ...
- 【1】学习C++时,一些零散知识点01
1.编程理念 学习从学习完C后,接触了C++,最重要的便是编程理念的转变.C缩重视的是结构化编程,面对一个较大的程序,就将他分解成小型.便于管理的任务,如果分解后的任务还是偏难过大的话,那将这个任务继 ...
- 419 JQuery and BootStrap
把葵花宝典剩下的知识讲完了 又学习了bootstrap <link rel="stylesheet" href="css/bootstrap.css"&g ...
- C#创建 WebApi 项目
做web api 可以参考一下网友 C#进阶系列——WebApi 接口参数不再困惑:传参详解 - 懒得安分 - 博客园https://www.cnblogs.com/landeanfen/p/5337 ...
- [insight] debug
python: 1. print理解流程 print('xy1') print('xy2') 可以更好地跟踪函数的执行流程,分析代码 2. 用python库 import pdb; pdb.set_t ...
- java8---lambda表达式
语法糖 lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块).Lambda表 ...