【多线程(Thread)方法重点总结】分享一下,我当时学线程时的不懂之处。挑一些我觉得难点 分享给大家
多线程安全性问题 1.可见性 volatile可以解决可见性 volatile是一个关键字 用来修饰成员变量(静态变量),解决变量的可见性,一旦变量发生改变,所有使用到该变量的线程都会取到最新值
2.有序性 volatile可以解决有序性 解决变量的有序性,一旦变量加上volatile,使编译器不会对代码进行”重排“
3.原子性 原子类:是对普通类型(比如:int,Integer,double,Double)的原子类封装,使其的操作成员原子操作。原子类的作用:对原子类的增加或者减少操作,保证是原子性,保证中间不会被其他线程"打断"。
比如:
AtomicInteger是对int变量进行操作的原子类
AtomicLong是对long变量进行操作的原子类
AtomicBoolean对boolean变量操作的“原子类”;
注意: 原子类,既可以解决原子性,也可以解决有序性和可见性
一: AtomicInteger类示例
****AtomicInteger的成员方法
public int getAndIncrement();//就相当于 变量++
public int incrementAndGet();//就相当于 ++变量****
方法使用 比如:
public static AtomicInteger a = new AtomicInteger(0);
二:AtomicIntegerArray类示例
方法使用 比如:
public static int[] intArray = new int[1000];//不直接使用数组
public static AtomicIntegerArray arr = new AtomicIntegerArray(intArray);
【线程安全解决、并发包】
一:synchronized关键字
格式一
synchronized(锁对象){
需要同步的代码(需要保持原子性的代码)
}
格式二
public synchronized void 方法名(){
需要同步的代码(需要保证原子性的代码)
}
格式三:Lock锁
ReentrantLock lock = new ReentrantLock();
lock.lock(); //加锁
需要同步的代码块(需要保持原子性的代码)
lock.unlock();//解锁
【并发包】
CopyOnWriteArrayList**是线程安全的
public static List<Integer> list = new CopyOnWriteArrayList<>();//保证线程安全 CopyOnWriteArraySet**是线程安全的
public static Set<Integer> set = new CopyOnWriteArraySet<>();//线程安全的
Hashtable**是线程安全的,但效率低
public static Map<Integer, Integer> map = new Hashtable<>(); //线程是安全的
ConcurrentHashMap**既安全又效率高
public static Map<Integer, Integer> map = new ConcurrentHashMap<>(); //线程是安全,但是效率高
CountDownLatch的作用**
允许当前线程,等待其他线程完成某种操作之后,当前线程继续执行
构造方法:
public CountDownLatch(int count); 需要传入计数器,需要等待的线程数
成员方法:
public void await() throws InterruptedException// 让当前线程等待
public void countDown() // 计数器进行减1
CyclicBarrier**的作用
让多个线程,都到达了某种要求之后,新的任务才能执行
构造方法:
public CyclicBarrier(int parties, Runnable barrierAction);
需要多少个线程 所有线程都满足要求了,执行的任务
成员方法:
public int await();当某个线程达到了,需要调用await()
Semaphore**的作用
用于控制并发线程的数量
构造方法:
public Semaphore(int permits); //参数 permits 表示最多允许有多少个线程并发执行
成员方法:
public void acquire(); //获取线程的许可证
public void release();//释放线程的许可证
Exchanger**的作用
用于线程间的数据交换
构造方法:
public Exchanger<V>();
成员方法:
public V exchange(V x);//参数为发给别的线程的数据,返回值别的线程发过来的数据
【线程池】
工具类中静态方法:创建一个线程池对象
public static ExecutorService newFixedThreadPool(int nThreads);
创建一个具有指定线程个数的线程池对象
如何向线程池中提交任务呢??
调用ExecutorService接口中规定的方法:
public Future<?> submit(Runnable task); 向线程池中提交无返回值的任务
public Future<T> submit(Callable<T> task);向线程池中提交有返回值的任务,返回Future类型,
.等待唤醒机制(Wait和Notify)
锁对象.notify方法只能唤醒一个线程,具体是哪一个是随机的
锁对象.notifyAll方法可以唤醒多个线程,谁抢到锁谁执行**
【定时器】
public Timer(): 构造一个定时器
public void schedule(TimerTask task,long delay);//在指定的时间之后执行指定的任务
public void schedule(TimerTask task,long delay,long period);//在指定的时间之后开始周期性的执行任务,周期的时间间隔是period
public void schedule(TimerTask task,Date time);//在指定的时间点执行指定的任务
public void schedule(TimerTask task,Date firstTime,long period);//在指定的时间点第一次执行任务,继续周期性执行任务,周期的时间间隔period