Java多线程
1、线程介绍
2、线程实现*(线程不一定执行看CPU调度安排!)
三中创建方式
(1):继承Thread类(重点,实现了Runnable接口)
//继承Thread类,重写run()方法 ,调用start开启线程
public class ThreadTest extends Thread {
@Override
public void run() {
//run方法线程体
for (int i=0;i<20;i++){
System.out.println("我在看代码-----"+i);
}
}
//main线程 主线程
public static void main(String[] args) {
//创建一个线程对象
ThreadTest threadTest1=new ThreadTest();
//调用start方法开启线程
threadTest1.start();
for (int i=0;i<2000;i++){
System.out.println("我在学习主线程--"+i);
}
}
}
不建议使用:避免OOP单继承局限性(oop即面向对象编程)
(2):实现Runnable接口(重点)
//创建线程方式2:实现runnable接口重写run方法,执行线程需要丢入Runnable接口实现类,调用start方法
public class RunnableTest implements Runnable {
@Override
public void run() {
//run方法线程体
for (int i=0;i<20;i++){
System.out.println("我在看代码-----"+i);
}
}
//main线程 主线程
public static void main(String[] args) {
//创建一个Runnable接口实习类对象
RunnableTest runnableTest=new RunnableTest();
//创建线程对象,通过线程对象来开启我们的线程,代理
new Thread(runnableTest).start();
for (int i=0;i<2000;i++){
System.out.println("我在学习主线程--"+i);
}
}
}
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
(3)多个线程操作一个对象(可能出现的问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱。)
//模拟归途赛跑
public class Race implements Runnable{
//获胜者
private static String winner;
@Override
public void run() {
for (int i=1;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==true) {
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("Winner is"+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race=new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
(4):实现Callable接口(了解,可以定义返回值,可以抛出异常)
public class CallAbleTest implements Callable<Boolean> {
private String url;//网络图片地址
private String name;//保存的文件名
public CallAbleTest(String url,String name){
this.url=url;
this.name=name;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallAbleTest testThread1=new CallAbleTest("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fs16.sinaimg.cn%2Fmiddle%2F48a45b954a11f806c240f%26690&refer=http%3A%2F%2Fs16.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621447755&t=0730edcc29228387e1c1d5a7af1d82ed","1.jpg");
CallAbleTest testThread2=new CallAbleTest("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fs16.sinaimg.cn%2Fmiddle%2F48a45b954a11f806c240f%26690&refer=http%3A%2F%2Fs16.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621447755&t=0730edcc29228387e1c1d5a7af1d82ed","2.jpg");
CallAbleTest testThread3=new CallAbleTest("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fs16.sinaimg.cn%2Fmiddle%2F48a45b954a11f806c240f%26690&refer=http%3A%2F%2Fs16.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621447755&t=0730edcc29228387e1c1d5a7af1d82ed","3.jpg");
//创建执行服务:
ExecutorService ser= Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1=ser.submit(testThread1);
Future<Boolean> r2=ser.submit(testThread2);
Future<Boolean> r3=ser.submit(testThread3);
//获取结果
boolean rs1=r1.get();
boolean rs2=r2.get();
boolean rs3=r3.get();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
//关闭服务
ser.shutdownNow();
}
@Override
public Boolean call() {
CallAbleTest.WebDownLoader webDownLoader=new WebDownLoader();
webDownLoader.downloader(url,name);
System.out.println("下载了文件名为:"+name);
return true;
}
class WebDownLoader{
// 下载方法
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Io异常,downloader方法出现问题");
}
}
}
}
3、静态代理
//静态代理
//静态代理模式总结:
//真实对象和代理对象都要实现一个接口
//代理对象要代理真实角色
//好处:
// 代理对象可以做很多真实对象做不了的事情
// 真实对象专注做自己的事情
//
public class StaticProxy01 {
public static void main(String[] args) {
You you=new You();
//thread实现了runnable接口
new Thread( ()-> System.out.println("我爱你!")).start();//lambda表达式
//-> 符号前面的括号里代表的是函数的入参,箭头右边表示的是函数的行为
new WeddingCompany(new You()).happyMarry();
// WeddingCompany weddingCompany=new WeddingCompany(new You());
// weddingCompany.happyMarry();
}
}
interface Marray{
void happyMarry();
}
//真实角色,1去结婚
class You implements Marray{
@Override
public void happyMarry() {
System.out.println("1:哈哈哈!结婚了");
}
}
//代理角色帮你结婚
class WeddingCompany implements Marray{
//代理真实目标角色
private Marray target;
public WeddingCompany(Marray target){
this.target=target;
}
@Override
public void happyMarry() {
before();
this.target.happyMarry();
after();
}
private void after() {
System.out.println("结婚后,收尾款");
}
private void before() {
System.out.println("结婚前,布置婚礼");
}
}
4、 Lamda表达式 (简化代码,函数式编程)
函数式接口(如果只包含一个抽象方法,那它就是一个函数式接口)
/*
* 推导lamda表达式
* */
public class LamdaTest01 {
//3、静态内部类
static class Like2 implements ILike{
@Override
public void lamda() {
System.out.println("I like lamda2");
}
}
public static void main(String[] args) {
ILike like=new Like();
like.lamda();
like=new Like2();
like.lamda();
//4、局部内部类
class Like3 implements ILike{
@Override
public void lamda() {
System.out.println("I like lamda3");
}
}
like=new Like3();
like.lamda();
//5、匿名内部类 ,没有类的名称,必须借助接口和父类
like = new ILike(){
@Override
public void lamda() {
System.out.println("I like lamda4");
}
};
like.lamda();
//6、lambda简化(jdk8之后)
like =() ->{
System.out.println("I like lamda5");
};
like.lamda();
}
}
//1、定义一个函数式接口
interface ILike{
void lamda();
}
//2、实现类
class Like implements ILike{
@Override
public void lamda() {
System.out.println("I like lamda");
}
}
为什么要使用lambda
1、避免匿名类定义过多
2、可以让你的代码看起来更简洁
3、去掉一堆没有意义的代码,只留核心的逻辑
public static void main(String[] args) {
ILover lover=new Love();
//1、lambda标识简化
lover=(int a)-> {
System.out.println(" i love you "+a);
};
lover.Love(520);
//2、参数类型
lover = (a)->{
System.out.println(" i love you "+a);
};
lover.Love(521);
//3、简化括号
lover = a->{
System.out.println(" i love you "+a);
};
lover.Love(522);
//4、去掉化括号
lover =a -> System.out.println(" i love you "+a);
lover.Love(523);
//总结:lambda表达式只能有一行代码的情况下,前提必须是接口必须是函数式接口
//多个参数也可以
}
interface ILover{
void Love(int a);
}
static class Love implements ILover{
@Override
public void Love(int a) {
System.out.println(" i love you "+a);
}
}
5、 线程的状态
不推荐stop()停止线程
(1)利用标志位停止线程
//测试stop
/*
* 1、建议线程正常停--》利用次数,不建议死循环
*2、建议使用标志位--》设置一个标志位
* 3、不要使用stop或则destory等果实或则jdk不建议使用方法
* */
public class StopTest implements Runnable {
//1|设置一个表示为
private boolean flag=true;
@Override
public void run() {
int i=0;
while (flag){
System.out.println("run....thread"+i++);
}
}
public void stop(){
this.flag=false;
}
public static void main(String[] args) {
StopTest test=new StopTest();
new Thread(test).start();
for (int i=0;i<1000;i++){
System.out.println("main "+i);
if (i==900){
//调用stop方法切换标志位
test.stop();
System.out.println("线程停止了!");
}
}
}
}
(2)线程休眠(1000ms=1s)
- sleep(时间)指定当前线程阻塞的毫秒数
- sleep存在异常InterruException
- sleep时间达到后线程进入就绪状态
- sleep可以模拟网络延迟,倒计时等。
- 每一个对象都有一个锁,sleep不会释放锁【重点】
public static void main(String[] args) {
Date startTime=new Date(System.currentTimeMillis());//获取系统当前时间
while (true){
//打印当前系统时间
try {
// tenDown();
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime=new Date(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//模拟倒计时
public static void tenDown() throws InterruptedException {
int num=10;
while (true){
Thread .sleep(1000);
System.out.println(num--);
if (num<=0){
break;
}
}
}
(3)线程礼让
-
礼让线程,让当前正在执行的线程暂停,但不阻塞
-
将线程冲运行状态转为就绪状态
-
让cup重新调度,礼让不一定成功!看cpu心情
-
package com.company.Yield; public class TestYield { public static void main(String[] args) { MyYield myYield=new MyYield(); new Thread(myYield,"a").start(); new Thread(myYield,"b").start(); } } class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"线程执行"); Thread.yield();//礼让 主要看cpu System.out.println(Thread.currentThread().getName()+"线程停止执行"); } }
(4)Join
- join合并线程,待此线程完成后,再执行其他线程,其他线程阻塞。
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println("线程vip来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin=new TestJoin();
Thread thread=new Thread(testJoin);
thread.start();
//主线程
for (int i = 0; i <500 ; i++) {
if (i==200){
thread.join();
}
System.out.println("main"+i);
}
}
6、检测线程状态
//观察线程状态
public class state {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
for (int i = 0; i <5 ; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("//");
});
//观察状态
Thread.State state=thread.getState();
System.out.println(state);
//观察后启动
thread.start();
state=thread.getState();
System.out.println(state);
while (state != Thread.State.TERMINATED){
Thread.sleep(1000);
state = thread.getState();
System.out.println(state);
}
//thread.start(); 线程只能启动一次
}
}
7、线程的优先级(优先级建议设在start调度前)
【主要还是要看cup,有可能会出现性能倒置现象】
-
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程先执行。
-
线程优先级用数字表示,范围1-10
-
Thread.Min_PRIORITY=1;
-
Thread.Max_PRIORITY=10;
-
Thread.NORM_PRIORITY=5;
-
使用一下方式改变优先级
getPriority().setPriority(int xxx)
package com.company.Prority; public class TestPrority { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); MyPriority priority=new MyPriority(); Thread t1=new Thread(priority,"t1"); Thread t2=new Thread(priority,"t2"); Thread t3=new Thread(priority,"t3"); Thread t4=new Thread(priority,"t4"); Thread t5=new Thread(priority,"t5"); Thread t6=new Thread(priority,"t6"); t1.start(); t2.setPriority(1); t2.start(); t3.setPriority(4); t3.start(); t4.setPriority(Thread.MAX_PRIORITY); t4.start(); // t5.setPriority(-1); // t5.start(); // // t6.setPriority(11); // t6.start(); } } class MyPriority implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); } }
8、守护线程(daemon)
【守护线程不随主线程结束,随系统结束】
*线程分为用户线程和守护线程
*虚拟机必须确保用户线程执行完毕(用户线程例如:main线程)
*虚拟机不用等待守护线程执行完毕,如:后台记录操作日志,监控内存,垃圾回收等
package com.company.daemon; //测试守护线程 public class TestDaemon { public static void main(String[] args) { god god=new god(); you you=new you(); Thread thread=new Thread(god); thread.setDaemon(true);//默认是false:表示用户线程 thread.start(); new Thread(you).start(); } } class you implements Runnable{ @Override public void run() { for (int i = 0; i <36500 ; i++) { System.out.println("你一生都开心的活着"); } System.out.println("========goodbey world========"); } }class god implements Runnable{ @Override public void run() { while (true){ System.out.println("上帝保佑着你"); } } }
9线程的同步【重点(降低性能)】
多个线程操作同一个资源(并发)
如果一个优先级低的线程释放锁会导致优先级倒置,引起性能问题
处理并发问题:对象的等待池
1、形成条件【队列和锁(Synchronized)】解决安全性
#三大不安全案例(sleep可以扩大方法问题的发生性)#
bank案例
package com.company.Synchronized; public class BankSecurity { public static void main(String[] args) { Account account=new Account(100,"结婚基金"); BankService Me=new BankService(account,50,"我"); BankService girlfriend=new BankService(account,100,"girlfriend"); girlfriend.start(); Me.start(); } } class Account{ int money; String name; public Account(int money, String name) { this.money = money; this.name = name; } } class BankService extends Thread{ Account account; int drawingMoney; int nowMoney; public BankService(Account account,int drawingMoney, String name) { super(name); this.drawingMoney = drawingMoney; this.account = account; } @Override public void run() { if (account.money-drawingMoney <0){ System.out.println(Thread.currentThread().getName()+"钱不够取不了"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } account.money=account.money-drawingMoney; nowMoney=nowMoney+drawingMoney; System.out.println(account.name+"账户余额"+account.money); System.out.println(this.getName()+"手里的钱:"+nowMoney); } }
Ticket案例
//不完全买票 //线程安全有负数 public class TicketSecurity { public static void main(String[] args) { buyTicket buyTicket=new buyTicket(); new Thread(buyTicket,"你").start(); new Thread(buyTicket,"我").start(); new Thread(buyTicket,"他").start(); } } class buyTicket implements Runnable{ //票 private int ticket = 10; boolean flag=true; @Override public void run() { //买票 while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } private void buy() throws InterruptedException { if (ticket<=0){ flag=false; return; } //模拟延迟 // Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+"拿到"+ticket--); } }
List案例
public class ListSecurity { public static void main(String[] args) throws InterruptedException { List<String> list=new ArrayList<String>(); for (int i = 0; i < 10000 ; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } Thread.sleep(3000); System.out.println(list.size()); } }
同步方法Synchronized(影响效率)
同步块//锁的对象为变化量
for (int i = 0; i < 10000 ; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
private synchronized void buy() throws InterruptedException {
if (ticket<=0){
flag=false;
return;
}
// 模拟延迟
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"拿到"+ticket--);
}
@Override
public void run() {
synchronized (account){
if (account.money-drawingMoney <0){
System.out.println(Thread.currentThread().getName()+"钱不够取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money=account.money-drawingMoney;
nowMoney=nowMoney+drawingMoney;
System.out.println(account.name+"账户余额"+account.money);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
10、JUC安全类型的集合(处理并发问题的另一个方法JUC)
public class testJUC {
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>();
for (int i = 0; i <10000 ; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(3000);
System.out.println(list.size());
}
}
11、死锁
//死锁;多个线程互相抱着对方资源,然后形成僵持
public class DeathLocak {
public static void main(String[] args) {
Makeup g1=new Makeup(0,"灰姑娘");
Makeup g2=new Makeup(1,"白雪公主");
g1.start();
g2.start();
}
}
class Lipstick{
}
class Mirror{
}
class Makeup extends Thread{
//需要的资源只有一份,用static保证只有一份
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();
int choice;
String girlName;
Makeup(int choice,String girlName){
this.choice=choice;
this.girlName=girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//化妆,互相持有对方的锁,就是需要对方的资源
private void makeup() throws InterruptedException {
if (choice==0){
synchronized (lipstick){//获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(1000);
synchronized (mirror){
System.out.println(this.girlName+"获得镜子的锁");
}
}
}else {
synchronized (mirror){//获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
Thread.sleep(2000);
synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
}
解决办法
private void makeup() throws InterruptedException {
if (choice==0){
synchronized (lipstick){//获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(1000);
}synchronized (mirror){
System.out.println(this.girlName+"获得镜子的锁");
}
}else {
synchronized (mirror){//获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
Thread.sleep(2000);
} synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
}
}
}
12、Lock(锁)
可重入锁(ReentranLocak)
//测试lock锁
public class LockTest {
public static void main(String[] args) {
TestLocak2 locak2=new TestLocak2();
new Thread(locak2).start();
new Thread(locak2).start();
new Thread(locak2).start();
}
}
class TestLocak2 implements Runnable{
int ticket = 10;
//定义lock锁
private ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while (true){
try {
lock.lock();//枷锁
if(ticket>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticket--);
}else {
break;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
lock锁和可重入锁的对比
13 线程协作
生产者消费者模式(问题不是模式)
线程通信
分析
通信问题解决(并发协作模型)
(1)管程法
//测试:生产者消费者模型-->利用缓冲区解决:管程法
//生产者 消费者 产区 缓冲区
public class TestPC01 {
public static void main(String[] args) {
SynContainer container=new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container=container;
}
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
container.push(new Chicken(i));
System.out.println("生产了第"+i+"只鸡");
}
}
}
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container=container;
}
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("消费了第--->"+container.pop().id+"只鸡");
}
}
}
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer{
//需要一个容器大小
Chicken[] chickens=new Chicken[10];
//容器计数器
int count=0;
//生产者放入产品
public synchronized void push(Chicken chicken) {
//如果容器满了,就需要等待消费者消费
if (count==chickens.length){
//通知消费者消费,生产等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有满,我们就需要丢入产品
chickens[count]=chicken;
count++;
//通知消费者
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop() {
//判断能否消费;
if (count==0){
//等待生产者生产,消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
Chicken chicken =chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
(2)信号灯法
//型号灯法 标志位解决
public class TestPc02 {
public static void main(String[] args) {
TV tv=new TV();
new plyer(tv).start();
new Watcher(tv).start();
}
}
//生产者
class plyer extends Thread{
TV tv;
public plyer(TV tv){
this.tv=tv;
}
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
if (i%2 == 0){
this.tv.play("快乐大本营");
}else {
this.tv.play("斗鱼");
}
}
}
}
//消费者
class Watcher extends Thread{
TV tv;
public Watcher(TV tv){
this.tv=tv;
}
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
tv.watch();
}
}
}
//节目
class TV{
String voice;
boolean flag=true;
public synchronized void play(String voice){
if (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了"+voice);
//通知观众观看
this.notifyAll();
this.voice=voice;
this.flag=!this.flag;
}
public synchronized void watch(){
if (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观看了:"+voice);
//通知演员表演
this.notifyAll();
this.flag=!this.flag;
}
}
14、线程池
//测试连接池
public class TestPool {
public static void main(String[] args) {
//1、创建服务,创建线程池
//newFixedThreadPool 参数为线程池大小
ExecutorService service= Executors.newFixedThreadPool(10);//线程池大小
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//2、关闭连接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
15总结
public class Summary {
public static void main(String[] args) {
new MyThread1().start();
new Thread(new MyThread2()).start();
FutureTask<Integer> futureTask=new FutureTask<Integer>(new MyThread3());
new Thread(futureTask).start();
Integer integer= null;
try {
integer = futureTask.get();
System.out.println(integer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyThread1 extends Thread{
@Override
public void run() {
System.out.println("Thread1");
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println("Thread2");
}
}
class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("Thread3");
return 100;
}
}
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
15总结
public class Summary {
public static void main(String[] args) {
new MyThread1().start();
new Thread(new MyThread2()).start();
FutureTask<Integer> futureTask=new FutureTask<Integer>(new MyThread3());
new Thread(futureTask).start();
Integer integer= null;
try {
integer = futureTask.get();
System.out.println(integer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyThread1 extends Thread{
@Override
public void run() {
System.out.println("Thread1");
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println("Thread2");
}
}
class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("Thread3");
return 100;
}
}