day25(2)_线程安全问题+同步代码块+同步方法问题

/*
 * 卖票:同时两个窗口卖票

 使用Runnable方法来实现多线程;

package Threadsenior;

import java.util.ArrayList;

public class TicketService {
	private ArrayList<String> all;
	
	public TicketService(){
		
		all = new ArrayList<String>();
		all.add("01车01A");
		all.add("01车01B");
		all.add("01车01C");
		all.add("01车01D");
		all.add("01车01F");
		
		all.add("02车02A");
		all.add("02车02B");
		all.add("02车02C");
		all.add("02车02D");
		all.add("02车02F");
	}
	
		//查询是否还有余票
		public boolean hasTicket(){
			return all.size()>0;
		}
		//卖票
		public String sale(){
			return all.remove(0);
		}
	
}

 

public class TestTicketRunnable {
	public static void main(String[] args) {
		
		@SuppressWarnings("unused")
		MyRunnable my = new MyRunnable();
			
		Thread t1 = new Thread(my,"窗口一");	
		Thread t2 = new Thread(my,"窗口二");
		
		t1.start();
		t2.start();
	}
}
class MyRunnable implements Runnable{
	private TicketService ts = new TicketService();
	
	public void run(){
		while(true){
				synchronized(ts){
			if(ts.hasTicket()){
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+" sells "+ts.sale());
			}else{
				break;
			}
			}
		}
	}
}

运行结果如下:

窗口一 sells 01车01A
窗口二 sells 01车01B
窗口一 sells 01车01C
窗口二 sells 01车01D
窗口二 sells 01车01F
窗口二 sells 02车02A
窗口一 sells 02车02B
窗口一 sells 02车02C
窗口二 sells 02车02D
窗口一 sells 02车02F

 * 继承和实现接口的方式的区别
 * 1、共享数据
 * thread必须用static的方式,
 * runnable只需要用一个对象就可以
 * 
 * 2、选择对象时,比较方便
 * runnable可以直接用this对象,继承thread的方式不能用this
 * 
 * 3、继承有单继承限制,实现没有限制
 * 
 * 开发中尽量面向接口编程

 

 

为提高代码的可读性,将同步部分的代码封装起来

 *3、两种方式
 *(1)同步代码块
 *语法格式
 *synchronized(同步的锁对象){
 *        需要锁起来的代码:一个线程在运行这段代码期间,不想别的线程插入进来
 *}

public class TestTicket {
	public static void main(String[] args) {
		TicketSaler t1 = new TicketSaler("窗口一");
		TicketSaler t2 = new TicketSaler("窗口二");
		
		t1.start();
		t2.start();
	}
}

class TicketSaler extends Thread{
	private static TicketService ts = new TicketService();//多卖了一张票
	private String name;
	
	public TicketSaler(String name) {
		super(name);	
	}

	public void run(){
	while(true){	
		if(ts.hasTicket()){
			saleOneticket();
			}else{
				break;
			}
	}
	}

	
	public synchronized static void saleOneticket(){//继承的方式,采用静态方法,考量this是否可用,因为这里采用的是继承的方法,所以在这里this不合适
		if(ts.hasTicket()){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+" sell "+ts.sale());
		}
	}
}

 

 *(2)同步方法 
 *    如果你的一次任务是在一个方法中完成的,那么可以可以锁一个方法
 * 语法格式
 * 【修饰符】 synchronized 返回值类型 方法名 (【形参列表】) 【throws 异常列表】
 * 
 * 同步方法的锁对象
 * 费静态方法:this 考量这个this是否可以做为锁对象
 * 静态方法 :当前类的class
 *         每一个类型被加载内存中后都会生成一个Class对象来表示这个类型,
 *         只要是同一种类型,Class对象就是同一个

public class TestTicketRunnable {
	public static void main(String[] args) {
		
		@SuppressWarnings("unused")
		MyRunnable my = new MyRunnable();
			
		Thread t1 = new Thread(my,"窗口一");	
		Thread t2 = new Thread(my,"窗口二");
		
		t1.start();
		t2.start();
	}
}
class MyRunnable implements Runnable{
	private TicketService ts = new TicketService();
		
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){	
			if(ts.hasTicket()){
				saleOneticket();
				}else{
					break;
				}
		}
	}
	
	public synchronized void saleOneticket(){
		if(ts.hasTicket()){
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+" "//
						+ "sells "+ts.sale());
	
		}
	}
	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值