栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java线程池(锁 同步问题)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java线程池(锁 同步问题)

线程的同步
对于每个对象身上都有一把锁
它的状态不是1就是0
锁旗标
要让线程同步,只需要将多个线程拥有同一个锁旗标

synchronized(this){
    aa();
}

0和1是同步的this ,2和3同步的是this
public synchronized void aa(){
    
}
public synchronized void bb(){
    
}

(JVM运行时数据区包含以下5个部分)
虚拟机的线程私有区间:
堆,方法区是属于线程共享区间
栈,本地方法栈,程序计数器属于线程独有的


线程的死锁
互相拿着对方的锁旗标,但是需要对方解锁


看图了解状态

线程状态JDK版(官方版):state
总共6种状态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED


Object对象有2个方法,
当被对象wait()时,进入等待状态
一个是wait()
一个是notifyAll()
suspend()与wait()的区别
suspend是线程的方法,实将当前线程挂起并且不会放对象的锁
wait()是对象的方法,但是实际是在操作改对象身上的线程,它调用后会放对象的锁
resume()与notify()的区别


==========================================
线程的同步

课堂案例:有2个线程,1个从1-->26,1个从A-Z
输出的效果是:1A2B3C....

输出的效果是:1AB2CD3EF4GH。。13YZ14ab。。。


 生产者与消费者
 线程间通讯(wait,notify)
 产品最多积压10个,当数量达到10,我们就不能
 生成,要等着消费
 产品没有货为0个,我们就不能消费,要等着生产
  生产者与消费者模式
  生产者类 可被线程操作
  消费者类 可被线程操作
  产品类


对于多线程而言有原子性与可见性

锁的概念:
CAS原理(原子操作可以采用java.util.concurrent.atomic相关类)
Compare And Swap(比较交换技术)
自旋锁

悲观锁(synchronized)乐观锁(CAS):
公平锁/非公平锁(Synchronized):拿锁与申请顺序
独享锁/共享锁:是否多个线程共有(广义)
互斥/读写:狭义
可重入锁:是否需要再次申请锁

 public synchronized void a(){
    b();
 }
public synchronized void b(){    
 }


 synchronized优化:(jdk1.5之后)
 无锁:CAS模式
 偏向【心】锁:假设只有一个线程,第一次进入synchronized,会在对象头中记录线程的ID,以后进入直接比较发现一致,就进入
 轻量锁:假设只有二个线程,当第一次进入synchronized锁住对象,那么另一个线程发生自旋(锁)
 重量锁:就是一般情况
 对于锁而言只有升级,没有降级

=============================================

线程的一些方法
yield与jion的区别
yield是当前线程抢到CPU,就让出CPU,重新抢
jion将交错运行的线程变成顺序执行的线程,
加入的线程执行完之后,再回头执行原来的线程
interrupt:通知线程改成中断状态

首先,一个线程不应该由其他线程来强制中断或停止,
而是应该由线程自己自行停止
Thread.stop, Thread.suspend, Thread.resume 
都已经被废弃了
1.阻塞状态下直接抛出异常
2.运行状态下修改标志继续运行


锁:Lock----》ReentrantLock 的使用

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();


手动上锁:lock
手动解锁:unlock
类似wait方法:condition.await
类似notifyAll方法:condition.signalAll
可中断等待:trylock

ReentrantLock与synchronized区别
synchronized:非公平,悲观,独享,互斥,可重入
ReentrantLock:非公平(可改),悲观,独享,互斥,可重入
粒度

synchronized对于多条件上锁需要多次上锁(嵌套)
ReentrantLock对于多条件只要调用newCondition方法

synchronized对于并发不高的情况下性能优于ReentrantLock
并发高的情况下低于ReentrantLock


关于线程安全有3种
1.不安全
2.相对安全  Vector就是相对安全
3.绝对安全

volatile的作用
当一个线程修改变量的时候,是修改自己线程中的变量副本
其它线程对于该变量的修改是不可见的,volatile修饰的
变量属于全局内存共享,可以实时让其它线程可见

 
============================================
线程组:ThreadGroup(了解)
默认新建线程组属于创建它的线程所属的线程组
就是为了统一方便管理

ThreadGroup tg = new ThreadGroup();
tg.setPrority(10);
tg.setDeamon(true);
new Thread(tg).setDeamon(true);

一、多线程下载作业讲解

1.5
二、Callable的使用
FutureTask包装返回结果


三、什么是线程池,有什么作用?
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。


创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();  
  for (int i = 0; i < 10; i++) {  
   final int index = i;  
   try {  
    Thread.sleep(index * 1000);  
   } catch (InterruptedException e) {  
    e.printStackTrace();  
   }  
   cachedThreadPool.execute(new Runnable() {  
    public void run() {  
     System.out.println(index);  
    }  
   });  
  }  


线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。


创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);  
  for (int i = 0; i < 10; i++) {  
   final int index = i;  
   fixedThreadPool.execute(new Runnable() {  
    public void run() {  
     try {  
      System.out.println(index);  
      Thread.sleep(2000);  
     } catch (InterruptedException e) {  
      e.printStackTrace();  
     }  
    }  
   });  
  }  


  因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

创建一个定长线程池,支持定时及周期性任务执行。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);  
  scheduledThreadPool.schedule(new Runnable() {  
   public void run() {  
    System.out.println("delay 3 seconds");  
   }  
  }, 3, TimeUnit.SECONDS);  

  表示延迟3秒执行

   

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);  
  scheduledThreadPool.scheduleAtFixedRate(new Runnable() {  
   public void run() {  
    System.out.println("delay 1 seconds, and excute every 3 seconds");  
   }  
  }, 1, 3, TimeUnit.SECONDS);  

  表示延迟1秒后每3秒执行一次

  创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
 

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();  
  for (int i = 0; i < 10; i++) {  
   final int index = i;  
   singleThreadExecutor.execute(new Runnable() {  
    public void run() {  
     try {  
      System.out.println(index);  
      Thread.sleep(2000);  
     } catch (InterruptedException e) {  
      e.printStackTrace();  
     }  
    }  
   });  
  }  

  结果依次输出,相当于顺序执行各个任务

jdk1.7
ForkJoinPool pool = new ForkJoinPool();


打印0-300,小于50就输出,过大任务拆分
RecursiveAction:无返回:任务中只有fork,但是
主线程需要等待
pool.submit()
主线程等2秒
//pool.awaitTermination(2, TimeUnit.SECONDS);


数组求和
RecursiveTask:有返回:fork后还需要join
表示搜集分出做事情的结果
返回值为FutureTask

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/571810.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号