java线程开发

java线程开发

  1. 生产者、消费者

    wait() notifyall()

    商店: 货架–数组

    面包商:有多个 多线程 要往数组里方面包

    顾客: 买面包,只要买走了,唤醒面包商

  2. 线程池

    package com.qf.pro2103.day19;
    
    import java.lang.reflect.Executable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ThreadPoolDemo {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//创建固定数量的线程池
    		ExecutorService es=Executors.newFixedThreadPool(4);
    		//创建动态数量的线程池
    		//ExecutorService es2=Executors.newCachedThreadPool();
    		//线程池里只有一个线程
    		//ExecutorService es=Executors.newSingleThreadExecutor();
    		//创建任务
    		Runnable runnable=new Runnable(){
    			private  int ticket=50;
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				while(true){
    					synchronized (this) {
    						if(ticket<=0){
    							break;
    						}
    						System.out.println(Thread.currentThread().getName()+"买了"+ticket+"张票");
    						ticket--;
    					}
    				}
    			}
    			
    		};
    		//到线程池种获取线程来执行售票任务
    		for(int i=0; i<5; i++){
    			es.submit(runnable);
    		}
    		//销毁线程池,等待线程池里的所有线程都执行结束后才销毁
    		es.shutdown();
    	}
    
    }
    
    
  3. 使用Callable方式实现线程

    package com.qf.pro2103.day19;
    
    import java.util.concurrent.Callable;
    
    public class CallableDemo implements Callable<Integer> {
    
    	@Override
    	public Integer call() throws Exception {
    		// TODO Auto-generated method stub
    		System.out.println(Thread.currentThread().getName()+"开始计算");
    		int sum=0;
    		for(int i=1; i<=100; i++){
    			sum+=i;
    			Thread.sleep(100);
    		}
    		return sum;
    	}
    
    }
    
    package com.qf.pro2103.day19;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class TestCallableDemo {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		CallableDemo callable=new CallableDemo();
    		//把Callable接口的实现类,作为任务传递给Future
    		FutureTask<Integer> task=new FutureTask<Integer>(callable);
    		//再创建线程类
    		Thread t1=new Thread(task);
    		t1.start();
    		
    		//接收线程的返回结果
    		try {
    			//等待call执行完毕后,才返回结果
    			int sum=task.get();
    			System.out.println("计算结果是:"+sum);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (ExecutionException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    }
    
    
  4. 线程安全集合

    Lock锁:

    读写锁:

    互斥规则:写-写 互斥

    ​ 读-写 互斥

    ​ 读-读 不互斥

    适用场景:读操作较多,写操作较少时,提升了读的效率

package com.qf.pro2103.day19;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

public class ReadWriteLock {
	//创建读写锁
	private  ReentrantReadWriteLock rrl=new ReentrantReadWriteLock();
	//从读写锁中获取 读 锁
	private ReadLock readLock=rrl.readLock();
	//从读写锁中获取 写  锁
	private WriteLock writeLock=rrl.writeLock();
	
	private Lock lock=new ReentrantLock();
	
	private String value;
	
	//读
	public String getValue() {
		//使用读锁即可    如果多个线程同时读取,不互斥
		//readLock.lock();
		lock.lock();
		try{
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("读取:"+this.value);
			return value;
		}finally{
			//readLock.unlock();
			lock.unlock();
		}
	}
	//写
	public void setValue(String value) {
		//writeLock.lock();
		lock.lock();
		try{
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("写入:"+this.value);
			this.value = value;
		}finally{
			//writeLock.unlock();
			lock.unlock();
		}
	}

}

package com.qf.pro2103.day19;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestReadWrite {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService es=Executors.newFixedThreadPool(20);
		ReadWriteLock readWriteDemo=new ReadWriteLock();
		
		//任务
		Runnable read=new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				readWriteDemo.getValue();
			}
		};
		Runnable write=new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				readWriteDemo.setValue("贾玉堃:"+new Random().nextInt(100));
			}
		};
		//获取开始时间
		long start=System.currentTimeMillis();
		for(int i=0; i<2; i++){
			es.submit(write);
		}
		for(int i=0;i<18;i++){
			es.submit(read);
		}
		es.shutdown();
		while(!es.isTerminated()){
			
		}
		long end=System.currentTimeMillis();
		System.out.println("用时:"+(end-start));
	}

}

非线程安全的集合如何变为线程安全?

package com.qf.pro2103.day19;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

public class Demo1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayList<String> list=new ArrayList<String>();
		//线程安全的集合---加同步锁
		//效率低:读读之间  读写之间  写写之间  都互斥
		List<String> list2= Collections.synchronizedList(list);
		
		//线程安全
		//读读之间  读写之间 不互斥  只有写写才互斥  效率优于线程安全的ArrayList
		CopyOnWriteArrayList<String> list3=new CopyOnWriteArrayList<>();
		list.add("hello");
		
		HashSet<String> set=new HashSet<String>();
		Set<String> set2=Collections.synchronizedSet(set);
		//读读之间  读写之间 不互斥  只有写写才互斥  效率优于线程安全的HashSet
		Set<String> set3= new CopyOnWriteArraySet<>();
		
		HashMap<String, String> map=new HashMap<String,String>();
		//Map加锁后,等同于HashTable   对整个数组加锁
		Map<String, String> map2= Collections.synchronizedMap(map);
		
		//线程安全的效率高的Map:不是对整个数组加锁,而是对数组元素及链表加锁
		//分段锁,最优情况下ConcurrentHashMap是线程安全的HashMap效率的16倍
		ConcurrentHashMap<String, String> cMap=new ConcurrentHashMap<String,String>();
		
		
	}

}

队列:

package com.qf.pro2103.day19;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Demo2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//声明队列
		//参数:队列里允许存放的值的个数
		Queue<String> stuQueue=new ArrayBlockingQueue<String>(3);
		Queue<String> stuQueue2=new LinkedBlockingQueue<String>(3);
		//添加数据
		//add() 如果达到队列的上限,会抛出异常
		//offer() 添加元素,达到上限后,返回false
		stuQueue.add("jiayukun");
		stuQueue.add("dongjiaxin");
		stuQueue.add("zhuhongtao");
		//先进先出
		//poll() 获取队列中的第一个元素,获取后删除
		//peek() 获取第一个元素,但是不删除
		String getStr=stuQueue.poll();
		System.out.println(getStr);
		String getStr2=stuQueue.poll();
		System.out.println(getStr2);
	}

}

总结:

1、阻塞: sleep() join() sync同步锁 wait()

​ 处于wait的线程需要notify()唤醒

【面试题】wait和sleep的区别?

  • 1、所属类不同 sleept是Thread类的 wait是Object
  • 2、sleep()可以用在任何位置(有、无锁都可以) wait()只能用在锁中
  • 3、sleep()在睡眠时,锁依然有效,而wait()会释放锁

2、生产者消费者模式

3、线程池 为什么用? 线程池的创建方式

4、实现Callable接口实现线程

5、Lock

​ 重点: 读写锁

6、线程安全的集合

7、队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值