并发谈nv朋友(多线程详解)
Process 、Thread
- 继承 Thread 类
- 实现Runnable 接口
- 实现Callable接口
继承 Thread 类
子类继承Thread 类具备多线程能力
启动线程:子类对象.start();
不建议使用:避免OOP单继承局限性
实现Runnable 接口
实现接口Runnable具备多线程能力
启动线程:传入目标对象+Thread对象.start();
推荐使用:避免单继承局限性、灵活方便,方便同一对象被多个线程使用
并发问题
龟兔赛跑
package thread;
//模拟龟兔赛跑
public class Rabbitgame implements Runnable {
//胜利者
private static String winner;
public static void main(String[] args) {
Rabbitgame race = new Rabbitgame();
new Thread(race, "兔子").start();
new Thread(race, "乌龟").start();
}
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
//模拟兔子休息
if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否已经结束
boolean flag = gameover(i);
//如果比赛结束,就终止程序
if (flag) {
break;
}
System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "步");
}
}
//判断是否完成比赛
private boolean gameover(int steps) {
//判断是否有胜利者
if (winner != null) {//已经存在胜利者
return true;
}
{
if (steps >= 100) {
winner = Thread.currentThread().getName();
System.out.println("winer is" + winner);
return true;
}
}
return false;
}
}
/*
兔子-->跑了0步
乌龟-->跑了0步
兔子-->跑了1步
乌龟-->跑了1步
兔子-->跑了2步
乌龟-->跑了2步
兔子-->跑了3步
兔子-->跑了4步
兔子-->跑了5步
兔子-->跑了6步
兔子-->跑了7步
兔子-->跑了8步
兔子-->跑了9步
乌龟-->跑了3步
乌龟-->跑了4步
乌龟-->跑了5步
乌龟-->跑了6步
乌龟-->跑了7步
乌龟-->跑了8步
乌龟-->跑了9步
乌龟-->跑了10步
乌龟-->跑了11步
乌龟-->跑了12步
乌龟-->跑了13步
乌龟-->跑了14步
乌龟-->跑了15步
乌龟-->跑了16步
乌龟-->跑了17步
乌龟-->跑了18步
乌龟-->跑了19步
乌龟-->跑了20步
乌龟-->跑了21步
乌龟-->跑了22步
乌龟-->跑了23步
乌龟-->跑了24步
乌龟-->跑了25步
乌龟-->跑了26步
乌龟-->跑了27步
乌龟-->跑了28步
乌龟-->跑了29步
乌龟-->跑了30步
乌龟-->跑了31步
乌龟-->跑了32步
乌龟-->跑了33步
乌龟-->跑了34步
乌龟-->跑了35步
乌龟-->跑了36步
乌龟-->跑了37步
乌龟-->跑了38步
乌龟-->跑了39步
乌龟-->跑了40步
乌龟-->跑了41步
乌龟-->跑了42步
乌龟-->跑了43步
乌龟-->跑了44步
乌龟-->跑了45步
乌龟-->跑了46步
乌龟-->跑了47步
乌龟-->跑了48步
乌龟-->跑了49步
乌龟-->跑了50步
乌龟-->跑了51步
乌龟-->跑了52步
乌龟-->跑了53步
乌龟-->跑了54步
乌龟-->跑了55步
乌龟-->跑了56步
乌龟-->跑了57步
乌龟-->跑了58步
乌龟-->跑了59步
乌龟-->跑了60步
乌龟-->跑了61步
乌龟-->跑了62步
乌龟-->跑了63步
乌龟-->跑了64步
乌龟-->跑了65步
乌龟-->跑了66步
乌龟-->跑了67步
乌龟-->跑了68步
乌龟-->跑了69步
乌龟-->跑了70步
乌龟-->跑了71步
乌龟-->跑了72步
乌龟-->跑了73步
乌龟-->跑了74步
乌龟-->跑了75步
乌龟-->跑了76步
乌龟-->跑了77步
乌龟-->跑了78步
乌龟-->跑了79步
乌龟-->跑了80步
乌龟-->跑了81步
乌龟-->跑了82步
乌龟-->跑了83步
乌龟-->跑了84步
乌龟-->跑了85步
乌龟-->跑了86步
乌龟-->跑了87步
乌龟-->跑了88步
乌龟-->跑了89步
乌龟-->跑了90步
乌龟-->跑了91步
乌龟-->跑了92步
乌龟-->跑了93步
乌龟-->跑了94步
乌龟-->跑了95步
乌龟-->跑了96步
乌龟-->跑了97步
乌龟-->跑了98步
乌龟-->跑了99步
winer is乌龟
* */
实现Callable接口
step1:创建一个Callable接口的实现类,需要返回值类型
step2:重写call方法,需要抛出异常
step3:创建目标对象
step4:创建执行服务
step5:提交执行
step6:获取结果
step7:关闭服务
import java.util.concurrent.*;//JUC并发编程包
public class CallableTest implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("线程"+Thread.currentThread().getName()+"执行了");
return true;
}
public static void main(String[] args) {
CallableTest c1 = new CallableTest();
CallableTest c2 = new CallableTest();
//创建线程池执行服务,传入线程数
/*
newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池,
以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。
如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。
如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。
在某个线程被显式地关闭之前,池中的线程将一直存在。
*/
ExecutorService executorService = Executors.newFixedThreadPool(2);
//提交执行
//Future 表示异步计算的结果。
// 它提供了检查计算是否完成的方法,以等待计算的完成,
// 并获取计算的结果。计算完成后只能使用 get 方法来获取结果
Future<Boolean> result1 = executorService.submit(c1);
Future<Boolean> result2 = executorService.submit(c2);
//获取结果
try {
Boolean resultA = result1.get();
Boolean resultB = result2.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
//在finally中关闭服务可以最大程度保证线程池的安全
executorService.shutdownNow();
}
}
}
静态代理模式
静态代理模式:StaticProxy
代理对象和真是对象都要实现同一个接口
代理对象要代理真是角色
注意的是,静态代理的函数,随着传入参数不同,目标对象也就会调用不同的参数
/*
婚庆公司就是Thread
静态代理模式:StaticProxy
代理对象和真是对象都要实现同一个接口
代理对象要代理真是角色
*/
public class StaticProxy {
public static void main(String[] args) {
You you = new You();
My my = new My();
WedCompany wedCompany = new WedCompany(you);
WedCompany wedCompany2 = new WedCompany(my);
wedCompany.HappyMarry();
wedCompany2.HappyMarry();
}
}
//结婚接口
interface Marry{
public void HappyMarry();
}
//真是角色,你去结婚
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("我要结婚了,我很高兴!!!");
}
}
class My implements Marry{
@Override
public void HappyMarry() {
System.out.println("结婚的不是我,哭死!!!");
}
}
//婚庆公司,婚庆公司代理你把一些事情
class WedCompany implements Marry{
private Marry target;//结婚客户
@Override
public void HappyMarry() {
System.out.println("结婚之前,布置现场");
//这个就是真是对象,随着传入的参数不同,target不同调用不同对象的HappyMarry()
this.target.HappyMarry();
System.out.println("结婚之后,守尾款");
}
public WedCompany(Marry target) {
this.target = target;
}
}