Java学习笔记——35多线程02

线程同步

  • 线程同步
    • 卖票案例
      • 同步代码块
      • 同步方法块
    • 线程安全的类
      • StringBuffer
      • Vector
      • Hashtable
    • Lock锁

线程同步

卖票案例

public class SellTicket implements Runnable{
    private int tickets=10;
    @Override
    public void run(){
        while (true){
            if(tickets>0){
                System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张票");
                tickets--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st= new SellTicket();
        Thread t1=new Thread(st,"李昊");
        Thread t2=new Thread(st,"朱长坤");
        Thread t3=new Thread(st,"杨天伦");
        t1.start();
        t2.start();
        t3.start();
    }
}

相同的票出现了多次
出现了负数票
原因是线程执行的随机性导致的

同步代码块

锁多条语句操作共享数据,可以使用同步代码块实现

格式

	syschronized(任意对象){
		多条语句操作共享数据的代码
	}
public class SellTicket implements Runnable{
    private int tickets=10;
    private Object obj=new Object();
    @Override
    public void run(){
        while (true){
            synchronized(obj){
                if(tickets>0){
                    System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张票");
                    tickets--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}

同步的好处和弊端

  • 好处:解决了多线程的数据安全问题
  • 弊端:当线程很多时,因为每个线程都会去判断同步上的锁,很耗费资源,会降低运行速率
  • 同步方法块

    • 同步方法:就是把synchronized关键字加到方法上

    格式

    	修饰符 synchronized 返回值类型 方法名(方法参数){
    	
    	}
    
    public class SellTicket implements Runnable{
        private int tickets=10;
    
        private int x=0;
        @Override
        public void run(){
            while (true){
                if(x%2==0){
                    synchronized(this){
                        if(tickets>0){
                            System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                            tickets--;
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                }
                else{
                    sellTicket();
                }
                x++;
            }
        }
        private synchronized void sellTicket(){
            if(tickets>0){
                System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                tickets--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    

    同步方法的锁对象是this

    • 同步j静态方法:就是把synchronized关键字加到静态方法上
      同步静态方法的锁对象是 类名.class
    public class SellTicket implements Runnable{
        private static int tickets=10;
    
        private int x=0;
        @Override
        public void run(){
            while (true){
                if(x%2==0){
                    synchronized(SellTicket.class){
                        if(tickets>0){
                            System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                            tickets--;
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                }
                else{
                    sellTicket();
                }
                x++;
            }
        }
        private static synchronized void sellTicket(){
            if(tickets>0){
                System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                tickets--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    
    

    线程安全的类

    StringBuffer

    • 线程安全 ,可变的字符序列
    • 从版本JDK5开始,被StringBuilder替代。通常应该使用StringBuilder(非线程安全的)类,因为它支持所有相同的操作,并且更快,因为它不执行同步

    Vector

    从Java 2平台v1.2开始,该类改进了List接口,使其成为JavaCollections Framework的成员。与新的集合实现不同,Vector被同步。如果不需要线程安全的实现,建议使用ArrayList代替Vector

    Hashtable

    • 该类实现了一个哈希表,它将键映射到值。任何非null对象都可以用作键或者值
    • 从Java 2平台v1.2开始,该类进行了改进,实现了Map接口,使其成为JavaCollections Framework的成员。与新的集合实现不同,Hashtable被同步。如果不需要线程安全的实现,建议使用HashMap代替Hashtable

    **Collections.synchronizedList()**可返回线程安全的ArrayList
    同理map也可以Collections.synchronizedMap()

    Lock锁

    为了更清晰地表达如何加锁和释放锁,JDK5后提供了一个新的锁对象Lock

    Lock提供了比使用synchronized方法和语句更为广泛的锁定操作
    Lock中获得锁和释放锁的方法:

    • void lock():获得锁
    • void unlock():释放锁

    Lock接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化

    构造方法:ReentrantLock():创建一个ReentrantLock的实例

    public class SellTicket implements Runnable{
        private int tickets=20;
        private Lock lock=new ReentrantLock();
        @Override
        public void run(){
            while (true){
                try{
                    lock.lock();
                    if (tickets>0){
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets+"张av");
                        tickets--;
                    } 
                }finally {
                    lock.unlock(); 
                }
                
            }
        }
    }
    
    

你可能感兴趣的:(从零开始Java学习,java,学习,笔记)