海阔天空

当前时间为:
欢迎大家来到海阔天空https://www.9713job.com,广告合作以及淘宝商家推广请微信联系15357240395

2020java教程:高级多线程

未分类
2020-08-30 12:53:38
1822677238@qq.com

手机扫码查看

2020java教程:高级多线程

高级多线程

线程池概念
现有问题:
线程是宝贵的内存资源、单个线程约占1MB空间,过多分配易造成内存溢出。
频繁的创建及销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降。

线程池
线程容器,可设定线程分配的数量上限。
将预先创建的线程对象存入池中,并重用线程池中的线程对象。
避免频繁的创建和销毁。

线程池原理

将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。

获取线程池
常用的线程池接口和类(java.util.concurrent)
Executor:线程池的顶级接口
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务代码
Executors工厂类:通过此类可以获得一个线程池。
通过newFixedThreadPool(int nThreads)获取固定数量的线程池。
参数:指定线程池中线程的数量。
通过newCachedThreadPool()获得动态数量的线程池,如不够则创建新的,没有上限。

线程池方法
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的进程。
在任何时候,最多nThreads线程处于主动处理任务。如果所有线程处于活动状态时都会提交其他任务,则它们将等待队列中直到线程可用。
如果任何线程由于在关闭之前的执行期间发生故障而终止,则如果需要执行后续任务,则新线程将占用它。
线程池线程将存在,直到它明确地为shutdown。

public static ExecutorService newCaChedThreadPool()
创建一个根据需要创建新线程的线程池,但在可用时将重新使用以前构造的线程。
这些线程池通常会提高执行许多短暂异步任务的程序的性能。
调用execute将重用以前构造的线程(如果可用)。如果没有可用的线程,将创建一个新的线程并将其添加到池中。
未使用60秒的线程将被终止并从缓存中删除。
因此,长时间保持闲置的池将不会消耗任何资源。
请注意,可用使用ThreadPoolExecutor构造函数创建具有相似属性但不同详细信息的池。
例如,超时参数

Callable接口
public interface Callable<V>{
public V call() throw Exception;
}

JDK5.0加入,与Runnable接口类似,实现之后代表一个线程任务。
Callable具有泛型的返回值、可用声明异常。

Future接口
概念:异步接收ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值
方法: V get() 以阻塞形式等待Future中的异步处理结果(call()的返回值)

线程的同步
同步:形容一次方法调用,同步一旦开始,调用者必须等待该方法返回,才能继续。

线程的异步
异步:形容一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立刻返回。二者竞争时间片,并发执行。

Lock接口
JDK5.0加入,与synchronized比较,显示定义,结构更灵活。
提供更多实用性方法,功能更强大、性能更优越。
常用方法:
void lock()//获取锁,如锁被占用,则等待
boolean tryLock()//尝试获得锁(成功返回true,失败返回false,不阻塞)
void unlock()//释放锁

重入锁
ReentrantLock:Lock接口的实现类,与synchronized一样具有互斥锁功能
private Lock locker=new ReentrantLock();//创建重入锁对象
locker.lock();//开启锁
locker.unlock();//释放锁,放入到finally块中

读写锁
ReentrantReaderWriterLock:
一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁。
支持多次分配读锁,使多个读操作可以并发执行。
互斥规则:
写-写:互斥,阻塞。
读-写:互斥,读阻塞写,写阻塞读。
读-读:不互斥、不阻塞。
在读操作远远高于写操作的环境中,可在保证线程安全的情况下,提高运行效率。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class demos{
    public static void main(String[] args) {
        Student s=new Student();
        long start=System.currentTimeMillis();
        ExecutorService es= Executors.newFixedThreadPool(20);
        Thread t1=new Thread(){
            @Override
            public void run() {
                try{s.getAge();}catch (Exception e){}
            }
        };
        Thread t2=new Thread(){
            @Override
            public void run() {
                try{s.setAge(18);}catch (Exception e){}
            }
        };
        for(int i=0;i<2;i++){
            es.submit(t2);
        }
        for(int i=0;i<18;i++){
            es.submit(t1);
        }
        es.shutdown();
        System.out.println(System.currentTimeMillis()-start);
    }
}
class Student{
    private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
    ReentrantReadWriteLock.ReadLock rl=lock.readLock();
    ReentrantReadWriteLock.WriteLock wl=lock.writeLock();
    int age;
    public int getAge() throws Exception {
        rl.lock();
        try{
            Thread.sleep(1000);
            return this.age;
        }finally {
            rl.unlock();
        }
    }
    public void setAge(int age) throws Exception {
        wl.lock();
        try{
            Thread.sleep(1000);
            this.age=age;
        }finally {
            wl.unlock();
        }
    }
}

线程安全的集合
Collection体系集合下,除Vector以外的线程安全集合。

Collections中的工具方法
Collections工具类中提供了多个可以获得线程安全集合的方法。

public static <T> Collection<T> synchronizedCollection(Collection<T> c)
public static <T> List<T> synchronizedList(List<T> list)
public static <T> Set<T> synchronizedSet(Set<T> s)
public static <K,V>  Map<K,V> synchronizedMap(Map<K,V> m)
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
public static <K,V>  SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
JDK1.2提供,接口统一,维护性高,但性能没提升,均已synchronized实现。

CopyOnWriteArrayList
线程安全的ArrayList,加强版读写分离。
写有锁,读无锁,读写之间不阻塞,优先读写锁。
写入时,先copy一个容易副本,再添加新元素,最后替换引用。
使用方式与ArrayList无异。
List<Strint> list=new CopyOnWriteArrayList<String>();
list.add(“A”);

CopyOnWriteArraySet
线程安全的Set,底层使用CopyOnWriteArrayList实现。
唯一不同在于,使用addIfAbsent()添加元素,会遍历数组。
如存在元素,则不添加(扔掉副本)

Set<String> set=new CopyOnWriteArraySet<>();
set.add("A");

ConcurrentHashMap
初始容量默认为16段,使用分段锁设计。
不对整个Map加锁,而是为每个段加锁。
当多个对象存入同一个段时,才需要互斥。
最理想状态为16个对象分别存入16个段,并行数量16.
使用方式与HashMap无异。

Map<String,String> map=new ConcurrentHashMap<>();
map.put(key,value);

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注