目录
一:线程安全判断依据
二:解决线程安全问题实现(同步代码块)
1:格式
2:同步代码块的锁对象是谁?
3:同步方法的时候,锁对象又是谁呢?
4:静态同步方法,锁对象是谁?
三:卖票程序
1:分析
2:第一种实现多线程方法写卖票程序
3: 第二种实现多线程方法写卖票程序
4:注意事项
一:线程安全判断依据
1、是否存在多线程环境
2、是否存在共享数据/共享变量
3、是否有多条语句 *** 作着共享数据/共享变量
二:解决线程安全问题实现(同步代码块) 1:格式synchronized(锁对象){//对象要先创建可以是自定义类对象也可以是object类对象
synchronized加在方法上时在修饰符和返回值之间
需要同步的代码;
}
2:同步代码块的锁对象是谁?任意对象
package day32; public class SellTicketThread implements Runnable{//自定义类实现Runnable接口 int tickets=100;//定义票总量 boolean b =true;//一个布尔标识来控制程序的结束 Object o = new Object();//定义一个对象 @Override public void run() { while(b){ synchronized (o){//同步代码块 synchronized中传入o对象 if(tickets>0){ System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票");//打印窗口名字以及正在卖的票 } else{ b=false; } } } } }3:同步方法的时候,锁对象又是谁呢?
this
package day32; public class SellTicketThread implements Runnable{ int tickets=100; boolean b =true; @Override public void run() { sellTickets();//调用方法 } public void sellTickets(){ while(b){ synchronized (this){//传入this对象 if(tickets>0){ System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票"); } else{ b=false; } } } } }4:静态同步方法,锁对象是谁?
该静态同步方法所属那个类的字节码文件
字节码文件也属于一种对象。静态方法属于那个类的字节码文件即 类名.class
package day32; public class SellTicketThread implements Runnable{ static int tickets=100;//变量加static因为静态的方法只能调用静态的变量 static boolean b =true; @Override public void run() { sellTickets();//调用方法 } public static void sellTickets(){ while(b){ synchronized (SellTicketThread.class){//传入当前类节码文件 if(tickets>0){ System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票"); } else{ b=false; } } } } }三:卖票程序 1:分析
卖票程序是否满足以上线程安全条件
1、是否存在多线程环境 是,由于有三个线程模拟三个窗口
2、是否存在共享数据/共享变量 是 共享数据是100张票
3、是否有多条语句 *** 作着共享数据/共享变量 是
2:第一种实现多线程方法写卖票程序package day32; public class SellTicketThread1 extends Thread { static int tickets =100;//定义票数 boolean b =true;//定义标识 Object o =new Object(); @Override //重新run方法 public void run() { while(b){ synchronized (o){ if(tickets>0){ System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票"); } else{//如票数小于等于0,标识为false退出循环 b =false; } } } } }
package day32; public class SellTickets2 { public static void main(String[] args) { //创建自定义类对象 SellTicketThread1 sellTicketThread = new SellTicketThread1(); SellTicketThread1 sellTicketThread1 = new SellTicketThread1(); SellTicketThread1 sellTicketThread2 = new SellTicketThread1(); //他们设置名字 sellTicketThread.setName("窗口一"); sellTicketThread1.setName("窗口二"); sellTicketThread2.setName("窗口三"); //启动线程 sellTicketThread.start(); sellTicketThread1.start(); sellTicketThread2.start(); } }3: 第二种实现多线程方法写卖票程序
package day32; public class SellTicketThread implements Runnable{ int tickets=100;//定义票数 boolean b =true;//定义标识 Object o =new Object(); @Override //重新run方法 public void run() { while(b){ synchronized (o){ if(tickets>0){ System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票"); } else{//如票数小于等于0,标识为false退出循环 b =false; } } } } }
package day32; public class SellTickets { public static void main(String[] args) { SellTicketThread sellTicketThread = new SellTicketThread();//创建继承Runnable类对象 //将继承Runnable类对象传入Thread构造方法中创建三个线程 Thread w1 = new Thread(sellTicketThread, "窗口一"); Thread w2 = new Thread(sellTicketThread, "窗口二"); Thread w3 = new Thread(sellTicketThread, "窗口三"); //启动线程 w1.start(); w2.start(); w3.start(); } }4:注意事项
当有共享变量用继承thread类时变量要有public satatic修饰
有共享变量时最好用继承接口方式
因为锁是多个线程公用一个是唯一的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)