2019独角兽企业重金招聘Python工程师标准>>>
线程同步
线程同步是指多个线程对同一资源(同一对象、同一变量等)进行操作,就会产生线程同步的问题。
如下:
package org.zhanghua.javase.demo.thread;/*** 线程同步演示* * @author ZhangHua* */
public class SynchronizedTest1 implements Runnable {Timer timer = new Timer();public static void main(String[] args) {SynchronizedTest1 test = new SynchronizedTest1();Thread t1 = new Thread(test);Thread t2 = new Thread(test);t1.setName("t1");t2.setName("t2");t1.start();t2.start();}@Overridepublic void run() {timer.add(Thread.currentThread().getName());}
}/*** 如果访问公用资源(例如:多个对象同时访问一个资源的时候),就需要同步* * @author ZhangHua* */
class Timer {private static int num = 0;// 在方法前加关键字synchronized 表示当程序执行到该方法时,锁定当前对象public synchronized void add(String name) {// synchronized (this) {// 表示在执行这块{}代码的时候,锁定当前对象,其他对象进入不了,只有当这块{}代码执行完了之后,会自动释放当前对象num++;try {Thread.sleep(1000);} catch (InterruptedException e) {// e.printStackTrace();}System.out.println(name + "你是第" + num + "个访问timer的线程");// }}
}
如果上面不使用synchronized 线程同步,输出的结果会如下:
t2你是第2个访问timer的线程
t1你是第2个访问timer的线程
解决方法:
1、在方法前加关键字synchronized 表示当程序执行到该方法时,锁定当前对象
2、使用synchronized (this) {}表示在执行这块{}代码的时候,锁定当前对象,其他对象进入不了,只有当这块{}代码执行完了之后,会自动释放当前对象
死锁?如何造成死锁的出现?
2个线程在执行的过程,需要锁定对方对象,才能完成,就会死锁。
例如:A 需要锁定B,才能完成;B需要锁定A,才能完成
package org.zhanghua.javase.demo.thread;/*** 线程死锁演示* * @author ZhangHua* */
public class DeadLockTest implements Runnable {// 状态值public int flag = 0;static Object o1 = new Object();static Object o2 = new Object();@Overridepublic void run() {System.out.println("flag=" + flag);if (flag == 1) {// 如果flag=1,就执行synchronized{}并锁定,首先锁定o1,然后如果能锁定o2,就能执行完成synchronized (o1) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (o2) {System.out.println("1");}}}if (flag == 0) {// 如果flag=0,就执行synchronized{}并锁定,首先锁定o2,然后如果能锁定o1,就能执行完成// 锁定这2个线程就死锁了synchronized (o2) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (o1) {System.out.println("0");}}}}/*** 结果猜想: 程序卡死了,不动了,该进程永远运行* * @param args*/public static void main(String[] args) {DeadLockTest d1 = new DeadLockTest();d1.flag = 1;DeadLockTest d2 = new DeadLockTest();d2.flag = 0;Thread t1 = new Thread(d1);Thread t2 = new Thread(d2);t1.start();t2.start();// 解决死锁的解决方案:可以把锁的对象加大些,如果锁住对象内的2个小对象,有可能发现死锁,那么就加大,锁住整个对象就可以了}}
解决死锁的解决方案:可以把锁的对象加大些,如果锁住对象内的2个小对象,有可能发现死锁,那么就加大,锁住整个对象就可以了
生产者与消费者
package org.zhanghua.javase.demo.thread;/*** 生产者与消费者演示* * 模拟一个做汉堡包和吃汉堡包的过程* * @author Edward* */
public class ProducerConsumerDemo {public static void main(String[] args) {// 大概有如下的概念// 汉堡包// 生产者// 消费者// 装汉堡包的容器HamburgerStack stack = new HamburgerStack();Baker baker = new Baker(stack);Customer customer = new Customer(stack);Thread b1 = new Thread(baker);b1.start();Thread c1 = new Thread(customer);c1.start();}}/*** 汉堡包* * @author Edward* */
class Hamburger {private Integer id; // 编号 用于汉堡包public Hamburger() {}public Hamburger(Integer id) {this.id = id;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Overridepublic String toString() {return "汉堡包" + id;}}/*** 装汉堡包的容器(先进后出)* * @author Edward* */
class HamburgerStack {private Hamburger[] stack = new Hamburger[10]; // 用数组来装汉堡包,最多可以装10个private Integer index = 0; // 数组的指针/*** 向容器中放汉堡包* * @param hamburger*/public synchronized void push(Hamburger hamburger) {while (index==stack.length) {//就等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();stack[index] = hamburger; // 把汉堡放到第index的位置index++; // 更新index}/*** 从容器中取汉堡包* * @return*/public synchronized Hamburger pop() {while (index==0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();index--;return stack[index];}}/*** 面包师傅(生产者)* * @author Edward* */
class Baker implements Runnable {/*** 生产者怎么生成面包呢? 首先得是一个线程类,因为可能有多个面包师傅 首先有有一个装面包的容器*/private HamburgerStack stack;public Baker(HamburgerStack stack) {this.stack = stack;}/*** 面包师傅生产面包* * 假设每个面包师傅最多生成20个面包,就完成了工作* */@Overridepublic void run() {for (int i = 1; i <= 20; i++) {// 生成一个面包Hamburger hamburger = new Hamburger(i);// 向容器中放面包stack.push(hamburger);System.out.println("我做了一个:"+hamburger);// 生产一个面包,休息1000毫秒try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}public HamburgerStack getStack() {return stack;}public void setStack(HamburgerStack stack) {this.stack = stack;}}/*** 顾客 吃面包的人(消费者)* * @author Edward* */
class Customer implements Runnable {private HamburgerStack stack;public Customer(HamburgerStack stack) {this.stack = stack;}/*** 消费过程* * 从装汉堡的容器中,拿出一个汉堡包,然后吃掉* */@Overridepublic void run() {for (int i = 1; i <= 20; i++) {// 从容器中拿出一个汉堡包Hamburger hamburger = stack.pop();System.out.println("我吃了一个:" + hamburger);// 吃了休息一个1000毫秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public HamburgerStack getStack() {return stack;}public void setStack(HamburgerStack stack) {this.stack = stack;}}