最近忙着备考大学四年最后的两科,昨天刚考完大学所有的考试,但是大学专业是机械,但是自己热衷于IT行业,想往IT行业走,希望毕业后能成功进入到IT行业,只希望毕业能找到一份Java开发工程师的工作,这样我才能专研和学习到更高深的技术.希望在毕业前能学到一点Java的精髓,让我可以成功进入到IT行业,加油~


线程问题:

 package demosummary.threadsafety;

 public class Ticket implements Runnable{
//定义票数
private int ticket = 100;
/**
* 执行卖票方法
*/
@Override
public void run() {
//卖票窗口永久开启
while (true) {
//判断票是否卖完
if (ticket > 0) {
try {
//三秒卖一张票
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖:"+ticket--);
}
}
}
} package demosummary.threadsafety; public class TicketTest {
public static void main(String[] args) {
//创建线程任务对象
Ticket ticket = new Ticket();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
/**
* 执行结果
* 窗口2正在卖:79
* 窗口3正在卖:79
* 窗口1正在卖:-1
* 出现重复卖同一张票和负票,在现实中是不允许出现的
*/
}

  注意:执行结果出现两种问题

    1.出现不同窗口卖同一张票,把票卖了两次

    2.出现卖不存在的票

  注意:这两种问题称为线程不安全

  线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全

线程同步

  当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题。要解决上述多线程并发访问一个资源的安全性问题:也就是解决重复票与不存在票问题,Java中提供了同步机制 (synchronized)来解决

  方法:

    1. 同步代码块

    2. 同步方法

    3. 锁机制

同步代码块

  同步代码块: synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问

  格式:

    synchronized(同步锁){

      需要同步操作的代码

    }

  同步锁:对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁

    1. 锁对象 可以是任意类型。

    2. 多个线程对象  要使用同一把锁

  同步锁是谁?

    对于非static方法,同步锁就是this。

    对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。

  注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着 (BLOCKED)

 package demosummary.threadsafety;

 public class Ticket02 implements Runnable {
//定义票数
private int ticket = 100; Object lock = new Object();
/**
* 执行卖票方法
*/
@Override public void run() {
//卖票窗口永久开启
while (true) {
synchronized (lock) {
//判断票是否卖完
if (ticket > 0) {
try {
//三秒卖一张票
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + "正在卖:" + ticket--);
}
}
}
}
} package demosummary.threadsafety; public class TicketTest02 {
public static void main(String[] args) {
//创建线程任务对象
Ticket02 ticket = new Ticket02();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
}

  使用了同步代码块可以解决线程安全问题

同步方法

  同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。

  格式:

    public synchronized void method(){

      可能会产生线程安全问题的代码

    }

 package demosummary.threadsafety;

 public class Ticket03 implements Runnable {
private int ticket = 100; /**
* 执行卖票方法
*/
@Override
public void run() {
//卖票窗口永久开启
while (true) {
sellTicket();
}
} private synchronized void sellTicket() {
//判断票是否卖完
if (ticket > 0) {
try {
//三秒卖一张票
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取线程名称
String name = Thread.currentThread().getName();
System.out.println(name + "正在卖:" + ticket--);
}
}
} package demosummary.threadsafety; public class TicketTest03 {
public static void main(String[] args) {
//创建线程任务对象
Ticket03 ticket = new Ticket03();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
}

Lock锁

  java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象

  Lock锁也称同步锁,加锁与释放锁方法化了,如下

    public void lock() :加同步锁。

    public void unlock() :释放同步

 package demosummary.threadsafety;

 import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Ticket04 implements Runnable {
//定义票数
private int ticket = 100; //创建锁对象
Lock lock = new ReentrantLock();
/**
* 执行卖票方法
*/
@Override
public void run() {
//卖票窗口永久开启
while (true) {
//给线程加锁
lock.lock();
//判断是否邮票可卖
if (ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取线程当前名称
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖"+ticket--);
}
//释放线程锁
lock.unlock();
}
}
} package demosummary.threadsafety; public class TicketTest04 {
public static void main(String[] args) {
//创建线程任务对象
Ticket04 ticket = new Ticket04();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
}

最新文章

  1. BZOJ 1391: [Ceoi2008]order [最小割]
  2. Apache虚拟主机配置,实现多域名访问本地项目PHP空间,以及配置403Forbidden等错误的解决办法
  3. git push ERROR: missing Change-Id in commit message footer
  4. Chorme中启动阿里旺旺误点取消启动并记住选择,如何更改。
  5. 几种ESB(企业服务总线)介绍
  6. Apache 80 端口被占用无法重启解决办法
  7. 第3章 Struts2框架--2、完整的Struts2框架应用实例
  8. 《attodiskbenchmarks-v2.47》说明文件
  9. GitHub上可能用到的开源
  10. linux查看系统的日志的一些实用操作
  11. 游戏音频技术备忘 (四) Wwise Unreal Engine 集成代码浅析 (一)
  12. swift学习 - 计时器
  13. 自定义MVC框架---第二章
  14. ibatis实战之插入数据(自动生成主键)
  15. Docker学习之4——构建NGINX镜像
  16. Django model 字段详解
  17. mac安装navicat mysql破解版
  18. 论文笔记:Person Re-identification with Deep Similarity-Guided Graph Neural Network
  19. Json.Net 反序列化成匿名对象
  20. mysql 笔记(一)

热门文章

  1. 其他综合-CentOS7 安装 Jumpserver 跳板机
  2. 07.进程管理+作业控制+文件查找与压缩+文件压缩与打包+tar打包解包+NFS
  3. 笔记5:Django知识一
  4. 201777010217-金云馨《面向对象程序设计(Java)》第十二周学习总结
  5. IDEA写vue项目出现红色波浪线警告如何解决??
  6. 283.移动零 关于列表list与remove原理*****(简单)
  7. day5_configparser模块
  8. 【Spring Data JPA篇】项目环境搭建(一)
  9. Python进阶-VI 生成器函数进阶、生成器表达式、推导式
  10. 区块链自问自答 day2