七、线程生命周期

没错,线程也是有生命周期的。就好像人类有出生、儿童、青年、中年、晚年、死亡一般。下面是线程的生命周期图:

八、线程的安全问题

所谓线程不安全【并发问题】,举个例子来说,如卖票,会出现重票、错票等现象,这就是线程不安全的。

并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事

并发:一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事

如:

/**
* 创建三个窗口买票,共100张票。用Runnable接口实现
*/
public class RunMainRunnable {
public static void main(String[] args) {
Window window = new Window();
// 创建三个线程
Thread win1 = new Thread(window);
Thread win2 = new Thread(window);
Thread win3 = new Thread(window);
// 设置线程的名字
win1.setName("窗口一:");
win2.setName("窗口二:");
win3.setName("窗口三:");
// 启动线程
win1.start();
win2.start();
win3.start();
}
} class Window implements Runnable{
private int ticket = 100; // 定义100张票
@Override
public void run() {
while (true) {
if (ticket > 0) {
try {
Thread.sleep(100); // 调用此方法,让效果明显一点
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获取到了第"+ticket+"票");
ticket--;
}else{
break;
}
}
}
}

运行结果:出现了重票

问题分析:

之所以会出现重票、错票等问题,就是因为出现了线程不安全。【假设此时ticket=7】在if判断中,如当窗口一获得cpu后,首先判断ticket>0会真,执行打印语句输出“窗口一:获取到了第7票”,此时窗口二获得cpu【注意:窗口一并未执行“ticket--;”,ticket依然为7】,判断ticket>0为真,执行打印语句输出“窗口二:获取到了第7票”,此时窗口三获得cpu【注意:窗口二并未执行“ticket--;”,ticket依然为7】,判断ticket>0为真,执行打印语句输出“窗口三:获取到了第7票”。便会出现重票。这在实际生活当中,肯定是不允许的,那我们该如何解决线程的安全问题呢?

九、同步机制

在Java中,我们通过同步机制,来解决线程的安全问题。

方式一:同步代码块

synchronized(同步监视器){
//需要被同步的代码 }

说明:

  1. 什么是同步的代码?

    • 操作共享数据的代码,即为需要被同步的代码。
  2. 什么是共享数据?
    • 多个线程共同操作的变量。比如:ticket就是共享数据。
  3. 什么是同步监视器
    • 俗称:锁。任何一个类的对象,都可以充当锁。
    • 要求:多个线程必须要共用同一把锁。

方式二:同步方法

 如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明为同步的。

总结

好处:同步的方式,解决了线程的安全问题。

坏处:操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。 ---局限性

eg1:方式一:同步代码块

/**
* 创建三个窗口买票,共100张票。用Runnable接口实现
*/
public class RunMainRunnable {
public static void main(String[] args) {
Window window = new Window();
// 创建三个线程
Thread win1 = new Thread(window);
Thread win2 = new Thread(window);
Thread win3 = new Thread(window);
// 设置线程的名字
win1.setName("窗口一:");
win2.setName("窗口二:");
win3.setName("窗口三:");
// 启动线程
win1.start();
win2.start();
win3.start();
}
} /**
* 方式一;同步代码块
*/
class Window implements Runnable{
private int ticket = 100; // 定义100张票
private Object object = new Object();
@Override
public void run() {
while (true) {
synchronized (object){ // 同步代码块
if (ticket > 0) {
try {
Thread.sleep(100); // 调用此方法,让效果明显一点
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获取到了第"+ticket+"票");
ticket--;
}else{
break;
}
}
}
}
}

eg2:方式二:同步方法

/**
* 创建三个窗口买票,共100张票。用Runnable接口实现
*/
public class RunMainRunnable {
public static void main(String[] args) {
Window window = new Window();
// 创建三个线程
Thread win1 = new Thread(window);
Thread win2 = new Thread(window);
Thread win3 = new Thread(window);
// 设置线程的名字
win1.setName("窗口一:");
win2.setName("窗口二:");
win3.setName("窗口三:");
// 启动线程
win1.start();
win2.start();
win3.start();
}
} /*
方式二;同步方法
* */
class Window implements Runnable{
private int ticket = 100; // 定义100张票
@Override
public void run() {
while (true) {
show();// 调用同步方法
if (ticket == 0) {
break; // 用来结束循环
}
}
} // 定义一个私有方法
private synchronized void show() { // 加synchronized关键字,使其成为一位同步方法。同步监视器或锁即为:this
if (ticket > 0) {
try {
Thread.sleep(100); // 调用此方法,让效果明显一点
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获取到了第"+ticket+"票");
ticket--;
}
}
}

java 多线程-2的更多相关文章

  1. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  2. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  3. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  4. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  5. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  6. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  7. java 多线程 1 线程 进程

    Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报  分类: javaSE综合知识点(14)  版权声明:本文为博主原创文章,未经博 ...

  8. 一起阅读《Java多线程编程核心技术》

    目录 第一章 Java多线程技能 (待续...)

  9. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  10. java从基础知识(十)java多线程(下)

    首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...

随机推荐

  1. vue 公众号H5 使用微信JSAPI 录音 完整齐全

    官方文档必须首当其冲 1.微信jsAPI 录音文档 2.获取微信临时素材文档 首先H5录音功能的话 对于普通H5网上是有很多的方法 插件  但是兼容性很差 特别是对于ios 一开始想的是用H5 做个通 ...

  2. matlab使用libsvm入门教程——使用matlab安装配置libsvm以及一个svm分类实例

    前言 此教程专注于刚入门的小白, 且博客拥有时效性, 发布于2019年3月份, 可能后面的读者会发现一些问题, 欢迎底下评论出现的问题,我将尽可能更新解决方案. 我开始也在如何安装libsvm上出现了 ...

  3. python 文件读写with open模式r,r+,w,w+,a,a+的区别

    模式 可做操作 若文件不存在 是否覆盖 r 只能读 报错 - r+ 可读可写 报错 是 w 只能写 创建 是 w+ 可读可写 创建 是 a 只能写 创建 否,追加写 a+ 可读可写 创建 否,追加写

  4. ms14-064漏洞复现

    本博客最先发布于我的个人博客,如果方便,烦请移步恰醋的小屋查看,谢谢您! 这是我在实验室学习渗透测试的第五个漏洞复现,一个多小时便完成了.学长给的要求只需完成查看靶机信息.在指定位置创建文件夹两项操作 ...

  5. Alink漫谈(十九) :源码解析 之 分位点离散化Quantile

    Alink漫谈(十九) :源码解析 之 分位点离散化Quantile 目录 Alink漫谈(十九) :源码解析 之 分位点离散化Quantile 0x00 摘要 0x01 背景概念 1.1 离散化 1 ...

  6. firewall几个常用命令

    systemctl status firewalld firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --r ...

  7. Storm与SparkStreaming对比

    Storm与SparkStreaming对比 ◆ Spark Streaming 批处理的性能比Storm高出几十倍.◆ Streaming采用小批量模式,Storm是一条消息一条消息的计算.◆ St ...

  8. openVswitch(OVS)源代码分析之工作流程(flow流表查询)

    原文链接: openVswitch(OVS)源代码分析之工作流程(flow流表查询)

  9. 给你项目加个Mock吧

    mockjs官网:http://mockjs.com/ 一.简介 1.什么是mock 拦截请求,生成随机数据. 2.mock的使用场景 当后端接口还未完成的时候,前端需要一些数据来写页面,此时就需要M ...

  10. 【转】Camera 简介

    一.摄像头(CAMERA)又称为电脑相机.电脑眼等,它作为一种视频输入设备,在过去被广泛的运用于视频会议.远程医疗及实时监控等方面. 近年以来,随着互联网技术的发展,网络速度的不断提高,再加上感光成像 ...