JUC
2023-02-26 23:43:39 0 举报
AI智能生成
JUC
作者其他创作
大纲/内容
JUC基本概念
juc概念: Java 5.0提出的 <b>java.util.concurrent</b> 包(简称juc),提供了常用类;包括几个<b>小的、标准化的、可扩展的实用类</b>;没有这些类功能实现起来会很枯燥乏味<br>
juc包含的基本包 : ① java.util.concurrent ( java 工具 线程 )<br> ② java.util.concurrent.atomic ( java 工具 线程 原子性 )<br> ③ java.util.concurrent.locks ( java 工具 线程 锁 )<br>
并行和并发:
并行:<b>同一时刻,多任务同时执行</b>;需要多台处理器或多核CPU或多台机器;每个任务独立执行,互不干扰;不需要等待其他任务执行结果<br>
并发:<b>在一个时间段内,多任务交替执行</b>;每个任务都争抢CPU时间片,完成一部分任务后让出CPU资源供其他线程抢夺;由于<b>CPU切换速度过快,给人感觉像是在同一时间执行一样 ; <font color="#000000">同一时刻,访问统一资源</font></b>
进程和线程 :
进程 : <b>具有独立功能的程序</b>;关于某个数据集合的一次运行活动 ;<b>是系统动态执行的基本单元</b> ;进程既是基本的分配单元,也是基本的执行单元<br>
线程:通常在<b>一个进程中可以包含若干个线程,一个进程中至少有一个线程</b>。线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,<b>基本上不拥有系统资源</b>,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。是<b>进程中最小可执行单位</b><br>
wait 和 sleep <br>
wait : Object 类的方法 ; 使用会放开锁;供其他线程抢夺使用 ; 在哪里睡在哪里醒
sleep : Thread 类的方法 ; 使用时不会放开锁; 在哪里睡在哪里醒<br>
<b>线程的状态</b><br><br>(1)New 新建状态<br>(2)Runnable 运行状态<br>(3)Blocked 阻塞状态(如果遇到锁,线程就会变为阻塞状态等待另一个线程释放锁)<br>(4)Waiting 等待状态(无限期等待)<br>(5)Time_Waiting 超时等待状态(有明确结束时间的等待状态)<br>(6)Terminated 终止状态(当线程结束完成之后就会变成此状态)
创建线程种类 : ① 继承 Thread 类 ;<br> ② 实现 Runnable 接口;<br> ③ 用 Callable 接口;<br> ④ 用 ThreadPool 创建
创建线程方式 : 造对象创建 、 lambda表达式创建 、 匿名内部类创建
lamdba 表达式
Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。<br><br>Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “->“, 该操作符被称为 Lambda 操作符或剪头操作符。它将 Lambda 分为两个部分:<br><br>- 左侧:指定了 Lambda 表达式需要的所有参数<br>- 右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能<br>
<b>使用 : 复制小括号(形参列表),写死右箭头 ->,落地大括号 {方法实现}</b>
<b>没使用lamdba创建线程</b><br>new Thread ( new Runnable ( ){<br> @Override<br> <br>})<br>
使用lamdba创建线程<br><span style="font-weight: normal;">new Thread ( ( )->{ sout("...") ; }).start( );</span><br>
使用条件:只能使用在<b>函数式接口</b>上
函数式接口定义 :只能有一个抽象类、可以有静态方法和默认方法
<b>函数式接口的注解:@FunctionalInterface <br></b>不满足条件代码就会直接报红线
Synchronized<br>
<b>概念</b>:Synchronized方法支持一种简单的策略,用于防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读或写操作都通过Synchronized方法完成。<br>总结一句话:能够保证在同一时刻最多只有一个线程执行该段代码,以保证并发安全的效果。<br>
<b>用法</b>:synchronized是Java中的关键字,是一种同步锁<br><span style="font-size: inherit;"> <b> 1.</b> </span><font color="#ff0000" style="font-size: inherit;"><b>修饰代码块</b></font><span style="font-size: inherit;">:被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; </span><br> <b>2. <font color="#ff0000">修饰方法</font></b>:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;<br>
synchronized实现同步的基础:<span style="font-weight: normal;">Java中的每一个对象都可以作为锁。具体表现为以下3种形式:</span><br><font color="#ff0000"><br>1. 对于普通同步(sync)方法,锁是当前实例对象。<br>2. 对于静态同步(static sync)方法,锁是当前类的Class对象。<br>3. 对于同步方法块,锁是Synchonized括号里配置的对象<br><br></font><span style="font-weight: normal;"> 如果</span>一个实例对象的非静态同步方法<span style="font-weight: normal;">获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁;可是</span>不同实例对象<span style="font-weight: normal;">的非静态同步方法因为用的是</span>不同对象的锁<span style="font-weight: normal;">,所以毋须等待其他实例对象的非静态同步方法释放锁,就可以获取自己的锁。</span><br><span style="font-weight: normal;"> 所有的</span>静态同步方法用的是同一把锁<span style="font-weight: normal;">——类对象本身。不管是不是同一个实例对象,</span>只要是<font color="#ff0000">一个类</font>的对象<span style="font-weight: normal;">,一旦一个静态同步方法获取锁之后,其他对象的静态同步方法,</span>都必须等待该方法释放锁之后,才能获取锁。<br><span style="font-weight: normal;"> 而</span>静态同步方法(Class对象锁)与非静态同步方法(实例对象锁)之间是不会有竞态条件的。<br>
Synchronized 八锁问题结论:
<span style="color: rgb(0, 0, 0); font-weight: normal;">1. 标准访问,先打印短信还是邮件<br></span><font color="#000000"> </font><span style="color: rgb(0, 0, 0);"> MSM,Email</span><br><span style="color: rgb(0, 0, 0); font-weight: normal;">2. 停4秒在短信方法内,先打印短信还是邮件<br></span><font color="#000000"> SMS.Email;AA线程停4秒sleep不放锁,</font><font color="#ff0000">sleep阻塞不释放锁</font><br><span style="color: rgb(0, 0, 0); font-weight: normal;">3. 普通的hello方法,是先打短信还是hello<br></span><font color="#000000"> 无线程4秒阻塞情况下:SMS,hello;</font><font color="#ff0000">普通方法不受线程锁控制</font><font color="#000000">;但是BB线程后出现</font><br><font color="#000000"> 有线程4秒sleep阻塞情况下:hello,SMS</font><br><span style="color: rgb(0, 0, 0); font-weight: normal;">4. 现在有两部手机,先打印短信还是邮件<br></span><font color="#000000"> 无4s阻塞:SMS,Email ; </font><font color="#ff0000">普通同步方法,锁的是对象</font><font color="#000000">;AA比BB创建早;<br> 有4s阻塞:Email,SMS<br><span style="font-weight: normal;">5. 两个静态同步方法,1部手机,先打印短信还是邮件<br></span> SMS,Email ; </font><font color="#ff0000">静态同步方法,锁的是Class类</font><br><span style="color: rgb(0, 0, 0); font-weight: normal;">6. 两个静态同步方法,2部手机,先打印短信还是邮件<br></span><font color="#000000"> SMS,Email ; 静态同步方法锁的是Class类</font><br><span style="color: rgb(0, 0, 0); font-weight: normal;">7. 1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件<br></span><font color="#000000"> Email,SMS;</font><font color="#ff0000">静态同步方法和普通同步方法不存在竞态条件</font><br><span style="color: rgb(0, 0, 0); font-weight: normal;">8. 1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件<br></span> Email,SMS;静态同步方法和普通同步方法不存在竞态条件<br>
Synchronized 八锁问题代码:<br>
//资源类<br>class Phone {<br> //发消息方法,有锁<br> public synchronized void sendSMS() throws Exception {<br> //TimeUnit.SECONDS.sleep(4);<br> System.out.println("------sendSMS");<br> }<br> //发email方法,有锁<br> public synchronized void sendEmail() throws Exception {<br> System.out.println("------sendEmail");<br> }<br> //sayHello方法,无锁<br> public void getHello() {<br> System.out.println("------getHello");<br> }<br><br>}<br>//使用<br>public class Lock_8 {<br><br> public static void main(String[] args) throws Exception {<br><br> Phone phone = new Phone();<br> Phone phone2 = new Phone();<br><br> new Thread(() -> {<br> try {<br> phone.sendSMS();<br> } catch (Exception e) {<br> e.printStackTrace();<br> }<br> }, "AA").start();<br><br> Thread.sleep(100);<br><br> new Thread(() -> {<br> try {<br> phone.sendEmail();<br> //phone.getHello();<br> //phone2.sendEmail();<br> } catch (Exception e) {<br> e.printStackTrace();<br> }<br> }, "BB").start();<br> }<br>}<br>
实例:(简单的多线程买票)<br>
<br><br>
Synchronized 和 ReentrantLock 都具有可重入性 (详情键Lock的ReentrantLock中的对比)<br>
Lock锁<br>
介绍:相比同步锁,JUC包中的Lock锁的功能更加强大,它提供了各种各样的锁(公平锁,非公平锁,共享锁,独占锁……),所以使用起来很灵活。
分类 : 公平锁、非公平锁、独占锁 ( 排他锁、写锁)、共享锁(读锁)<br>
声明: Lock lock = new ReentrantLock( ); //非公平锁<br> Lock lock = new ReentrantLock(true); //公平锁<br> ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock( ); //非公平读写锁<br> ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true); <br> ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock( ); // 读锁<br> ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock( ); //写锁<br> <br>
0 条评论
下一页