多线程基础
2016-09-08 10:46
127 查看
/**
* 创建线程两种方式: 继承Thread父类, 实现Runnable接口
* ① 避免了java单继承的局限性
* ② 如果多个线程要操作同一份资源(或数据), 更适合使用实现的方式
*
* 线程安全问题,打印车票时,会出现重票,错票
* 1. 线程安全问题存在的原因?
* 由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在了安全问题。
* 2. 如何解决线程的安全问题?
* 必须让一个线程操作共享数据完毕以后,其他线程才有机会参与共享数据的操作.
* 方式一:同步代码块
* synchronized(同步监视器){
* 需要被同步的代码块(即为操作共享数据的代码)
* }
* 1. 共享数据:多个线程共同操作的同一个数据(变量)
* 2. 同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码块,俗称锁。
* 要求:所有的线程必须公用同一把锁!
* 注:在实现的方式中,考虑同步的话,可以使用 this 来充当锁。但是在继承的方式中,慎用this.
* 方式二:同步方法
* 将操作共享数据的方法声明为 synchronized 。即此方法为同步方法,能够保证当其中一个线程执行此方法时,
* 其他线程在外等待直至此线程执行完此方法。
* >同步方法的锁:当前对象 this 。
*/
* 创建线程两种方式: 继承Thread父类, 实现Runnable接口
* ① 避免了java单继承的局限性
* ② 如果多个线程要操作同一份资源(或数据), 更适合使用实现的方式
*
* 线程安全问题,打印车票时,会出现重票,错票
* 1. 线程安全问题存在的原因?
* 由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在了安全问题。
* 2. 如何解决线程的安全问题?
* 必须让一个线程操作共享数据完毕以后,其他线程才有机会参与共享数据的操作.
* 方式一:同步代码块
* synchronized(同步监视器){
* 需要被同步的代码块(即为操作共享数据的代码)
* }
* 1. 共享数据:多个线程共同操作的同一个数据(变量)
* 2. 同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码块,俗称锁。
* 要求:所有的线程必须公用同一把锁!
* 注:在实现的方式中,考虑同步的话,可以使用 this 来充当锁。但是在继承的方式中,慎用this.
* 方式二:同步方法
* 将操作共享数据的方法声明为 synchronized 。即此方法为同步方法,能够保证当其中一个线程执行此方法时,
* 其他线程在外等待直至此线程执行完此方法。
* >同步方法的锁:当前对象 this 。
*/
/** * 模拟火车站售票窗口, 开启三个窗口, 总票数为 100 * 采用继承的方式实现 */ public class TicketDemo_1 { public static void main(String[] args) { Object obj = new Object(); Window win1 = new Window(obj); Window win2 = new Window(obj); Window win3 = new Window(obj); win1.setName("窗口1"); win2.setName("窗口2"); win3.setName("窗口3"); win1.start(); win2.start(); win3.start(); } } // 存在线程的安全问题 ---> 使用同步代码块处理。 class Window extends Thread { private static int ticket = 100; private Object obj; public Window(Object obj) { super(); this.obj = obj; } @Override public void run() { while(true) { // synchronized (this) { // 在本问题中,this表示win1, win2, win3 synchronized (obj) { if (ticket > 0) { try { Thread.sleep(80); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 售票: 票号为 " + (ticket --)); } else { break; } } } } } /** * 模拟火车站售票窗口, 开启三个窗口, 总票数为 100 * 采用实现的方式+同步代码块方式实现 */ public class TicketDemo_2 { public static void main(String[] args) { WindowRunnable windowRunnable = new WindowRunnable(); Thread thread_1 = new Thread(windowRunnable); Thread thread_2 = new Thread(windowRunnable); Thread thread_3 = new Thread(windowRunnable); thread_1.setName("窗口1"); thread_2.setName("窗口2"); thread_3.setName("窗口3"); thread_1.start(); thread_2.start(); thread_3.start(); } } class WindowRunnable implements Runnable { /** * 多个线程共享一个对象的数据 */ private int ticket = 100; Object obj = new Object(); @Override public void run() { while(true) { synchronized (obj) { // this就是上面的windowRunnable,只有一个对象 if (ticket > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 售票: 票号为 " + (ticket --)); } else { break; } } } } } /** * 模拟火车站售票窗口, 开启三个窗口, 总票数为 100 * 采用实现的方式+同步方法方式实现 */ public class TicketDemo_3 { public static void main(String[] args) { WindowRunnable_1 windowRunnable = new WindowRunnable_1(); Thread thread_1 = new Thread(windowRunnable); Thread thread_2 = new Thread(windowRunnable); Thread thread_3 = new Thread(windowRunnable); thread_1.setName("窗口1"); thread_2.setName("窗口2"); thread_3.setName("窗口3"); thread_1.start(); thread_2.start(); thread_3.start(); } } class WindowRunnable_1 implements Runnable { /** * 多个线程共享一个对象的数据 */ private int ticket = 100; @Override public void run() { while(true) { if (sellTicket()) { break; } } } private synchronized boolean sellTicket() { if (ticket > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 售票: 票号为 " + (ticket --)); return false; } else { return true; } } }
相关文章推荐
- GSON TypeToken 解决泛型问题
- Linux系统分区
- Vagrant虚拟化之网络配置
- 响应式图像--图片自适应大小
- 【项目 0 - 宣告“主权”】
- Linux 设备驱动之字符设备(一)
- 第二周项目0-宣告“主权”
- android 开源 + 一些素材网站
- 用select下拉菜单来实现Ajax异步刷新
- GSON TypeToken 解决泛型问题
- swift GCD使用指南
- 项目0 - 宣告“主权”
- POJ 3675/2986(Telescope/A Triangle and a Circle-三角形与圆的面积并)
- 第二周项目3-体验复杂度-两种排序算法的运行时间
- snprintf函数的使用
- django数据查询优化annotate和aggregate
- 第二周 项目0-宣告“主权”
- 解析Android 中多点触摸的实现方法
- <hadoop学习历程>--笔记心得4-HDFS文件读写流程
- poj3690 Constellations