目录
1、概念
1.1、Process与Thread
1.2、核心概念
2、创建线程的三种方式
Java创建线程的方式:
2.1继承Thread类(方式一)
package com.sxt.thread;
/*
* 创建线程方式一:
* 1、创建:继承Thread类,重写run方法
* 2、启动:创建子类对象 + start
*/
public class StartThread extends Thread
{
/*
* 线程入口点
*/
@Override
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("一边听歌");
}
}
public static void main(String[] args)
{
//创建子类对象
StartThread st = new StartThread();
//启动
st.start(); //不保证立即运行,CPU调用
//st.run(); //普通方法调用
for(int i = 0; i < 10; i++)
{
System.out.println("一边coding");
}
}
}
2.2、实现Runnable(方式二)
package com.sxt.thread;
/*
* 创建线程方式一:
* 1、创建:实现Runnable + 重写run方法
* 2、启动:创建实现类对象 + Thread对象 + start
*
* 推荐:避免单继承的局限性,优先使用接口
* 方便共享资源
*/
public class StartThread02 extends Thread
{
/*
* 线程入口点
*/
@Override
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("一边听歌");
}
}
public static void main(String[] args)
{
//创建实现类对象
StartThread02 st = new StartThread02();
//创建代理对象
Thread t = new Thread(st);
//启动线程
t.start();
//简化:匿名对象
// new Thread(new StartThread02()).start();
for(int i = 0; i < 10; i++)
{
System.out.println("一边coding");
}
}
}
实现Runnable创建线程主要原因之一:共享资源、并发线程--》引入线程安全问题
package com.sxt.thread;
/*
* 共享资源(并发线程)
*/
public class Web12306 implements Runnable
{
//票数
int ticketNums = 90; //共享的资源
@Override
public void run()
{
while(true)
{
if(ticketNums < 0)
{
break;
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
}
public static void main(String[] args)
{
System.out.println(Thread.currentThread().getName());
//一份资源
Web12306 web = new Web12306();
//多个代理
new Thread(web, "森经理").start();
new Thread(web, "莹董事").start();
new Thread(web, "宝宝").start();
}
}
2.3、实现Callable(方式三)
JUC下实现Callable接口
代码模拟
package com.sxt.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CRacer implements Callable<Integer>
{
private String winner; //胜利者
@Override
public Integer call() throws Exception
{
for(int steps = 1; steps <= 100; steps++)
{
//模拟休息
if(Thread.currentThread().getName().equals("rabbit") && steps%10 ==0)
{
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + "-->" + steps);
//比赛是否结束
boolean flag = gameOver(steps);
if(flag)
{
return steps;
}
}
return null;
}
private boolean gameOver(int steps)
{
if(winner != null) //存在胜利者
{
return true;
}
else
{
if(steps == 100)
{
winner = Thread.currentThread().getName();
System.out.println("winner ==>" + winner);
return true;
}
}
return false;
}
public static void main(String[] args) throws Exception, Exception
{
CRacer racer = new CRacer();
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(2);
//提交执行
Future<Integer> result1 = ser.submit(racer);
Future<Integer> result2 = ser.submit(racer);
//获取结果
Integer r1 = result1.get();
Integer r2 = result2.get();
System.out.println(r1);
System.out.println(r2);
//关闭服务
ser.shutdown();
}
}
3、静态代理设计模式
package com.sxt.thread;
/*
* 静态代理
* 公共接口:
* 1、真实角色
* 2、代理角色
*/
public class StaticProxy
{
public static void main(String[] args)
{
new WeddingCompany(new You()).happyMarry();
//new Thread(线程对象).start();
}
}
interface Marry
{
void happyMarry();
}
//真实角色
class You implements Marry
{
@Override
public void happyMarry()
{
System.out.println("you and 嫦娥终于奔月了~");
}
}
//代理角色
class WeddingCompany implements Marry
{
//真实角色
private Marry target;
public WeddingCompany(Marry target)
{
this.target = target;
}
@Override
public void happyMarry()
{
ready();
this.target.happyMarry();
after();
}
private void ready()
{
System.out.println("布置桌椅");
}
private void after()
{
System.out.println("共享花烛夜");
}
}
4、lambda_简化线程
推导lambda
package com.sxt.thread;
/*
* 创建线程方式一:
* 1、创建:继承Thread类,重写run方法
* 2、启动:创建子类对象 + start
*/
public class LambdaThread
{
//静态内部类
static class Test implements Runnable
{
@Override
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("一边听歌");
}
}
}
public static void main(String[] args)
{
// new Thread(new Test()).start(); //测试静态内部类
//局部内部类
class Test2 implements Runnable
{
@Override
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("一边听歌");
}
}
}
// new Thread(new Test()).start(); //测试局部内部类
//匿名内部类(必须借助接口或者父类)
new Thread(new Runnable()
{
@Override
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("一边听歌");
}
}
}).start();
//JDK8 简化lambda
new Thread(() ->{
for(int i = 0; i < 10; i++)
{
System.out.println("lambda一边听歌");
}
}).start();
}
}
4.1、无参lambda表达式
package com.sxt.thread;
public class Lambda
{
static class Like2 implements Llike
{
@Override
public void lambda()
{
System.out.println("I kike lambda2");
}
}
public static void main(String[] args)
{
//外部类
Llike like = new Like();
like.lambda();
//静态内部类
like = new Like2();
like.lambda();
//局部内部类
class Like3 implements Llike
{
@Override
public void lambda()
{
System.out.println("I kike lambda3");
}
}
like = new Like3();
like.lambda();
//匿名内部类
like = new Llike() {
@Override
public void lambda()
{
System.out.println("I kike lambda4");
}
};
like.lambda();
//lambda表达式(必须存在类型)
like = () ->{
System.out.println("I kike lambda5");
};
like.lambda();
}
}
interface Llike
{
void lambda();
}
class Like implements Llike
{
@Override
public void lambda()
{
System.out.println("I kike lambda1");
}
}
4.2、带参数的lambda表达式
package com.sxt.thread;
public class LambdaTest02
{
public static void main(String[] args)
{
Llove love = (int a) ->{
System.out.println("I like lambda -->" + a);
};
love.lambda(5);
//简化(省去参数类型
Llove love2 = (a) ->{
System.out.println("I like lambda -->" + a);
};
love2.lambda(10);
//再简化(只有一个参数的话可以省略括号)
Llove love3 = a ->{
System.out.println("I like lambda -->" + a);
};
love3.lambda(20);
//再简化(只有一行代码,可以省略花括号)
Llove love4 = a ->System.out.println("I like lambda -->" + a);
love4.lambda(30);
}
}
interface Llove
{
void lambda(int n);
}
class Love1 implements Llove
{
@Override
public void lambda(int a)
{
System.out.println("I kike lambda --" + a);
}
}
4.3、带返回值的lambda表达式
package com.sxt.thread;
public class LambdaTest03
{
public static void main(String[] args)
{
Llnterest interest = (int a1, int a2) ->{
System.out.println(a1 + "-" + a2);
return a1 + a2;
};
System.out.println(interest.lambda(100, 200));
//简化
interest = (a1, a2) ->{
System.out.println(a1 + "-" + a2);
return a1 + a2;
};
System.out.println(interest.lambda(1000, 200));
//简化
interest = (a1, a2) -> a1 + a2;
System.out.println(interest.lambda(2000, 200));
}
}
interface Llnterest
{
int lambda(int a, int b);
}
4.4、线程中使用lambda
package com.sxt.thread;
public class LambdaThread02
{
public static void main(String[] args)
{
new Thread(()-> {
for(int i = 0; i < 10; i++)
{
System.out.println("一边学习");
}
}).start();;
new Thread(()-> {
for(int i = 0; i < 10; i++)
{
System.out.println("一边吃炸鸡");
}
}).start();;
}
}
5、线程状态
5.1、终止
package com.sxt.state;
/*
* 线程终止的两种方法
* 1、线程自动结束
* 2、设置一个标识量,让线程终止
*/
public class TerminateThread implements Runnable
{
//1、加入标记,标记线程是否可以运行
boolean flag = true;
private String name;
public TerminateThread(String name)
{
this.name = name;
}
@Override
public void run()
{
int i = 0;
//关联标识,true-->运行false-->停止
while(flag)
{
System.out.println(name + "-->" + i++);
}
System.out.println("exit");
}
//对外提供方法改变标识
public void terminate()
{
this.flag = false;
}
public static void main(String[] args)
{
TerminateThread tt = new TerminateThread("森森");
new Thread(tt).start();
for(int i = 0; i < 100; i++)
{
if(i == 88)
{
tt.terminate(); //线程终止
System.out.println("Game Over");
}
System.out.println("main -->" + i);
}
}
}
5.2、暂停sleep
package com.sxt.state;
/*
* 共享资源(并发线程)
*/
public class BlockedSleep implements Runnable
{
int ticketNums = 20;
@Override
public void run()
{
while(true)
{
if(ticketNums < 0)
{
break;
}
//模拟延时
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
}
public static void main(String[] args)
{
//一份资源
BlockedSleep web = new BlockedSleep();
System.out.println(Thread.currentThread().getName());
//多个代理
new Thread(web, "森经理").start();
new Thread(web, "莹董事").start();
new Thread(web, "宝宝").start();
}
}
5.3、礼让yield
- 礼让线程,让当前正在执行的线程暂停
- 不是阻塞线程,而是将线程从运行状态转入就绪状态
-让CPU调度器重新调度
package com.sxt.state;
/*
* yield礼让线程,暂停线程直接进入就绪状态而不是阻塞状态
*/
public class YieldDemo1
{
public static void main(String[] args)
{
MyYield yield = new MyYield();
new Thread(yield, "小森").start();
new Thread(yield, "小莹莹").start();
}
}
class MyYield implements Runnable
{
@Override
public void run()
{
System.out.println(Thread.currentThread().getName() + "-->");
Thread.yield(); //礼让
System.out.println(Thread.currentThread().getName() + "-->");
}
}
5.4、插队join
join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
package com.sxt.state;
public class BlockdedJoin1
{
public static void main(String[] args) throws InterruptedException
{
Thread t = new Thread(()-> {
for(int i = 0; i < 50; i++)
{
System.out.println("lambda..." + i);
}
});
t.start();
for(int i = 0; i < 50; i++)
{
if(i == 20)
{
t.join(); //插队,main被阻塞
}
System.out.println("main..." + i);
}
}
}
6、深度观察状态
6.1、线程进入就绪状态的情况
1、start()
2、线程阻塞接触
3、yield
4、jvm切换
6.2、线程进入阻塞的情况
1、sleep
2、join
3、wait
4、read、write
import java.lang.Thread.State;
public class AllState
{
public static void main(String[] args)
{
Thread t = new Thread(() ->{
for(int i=0;i<5;i++)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("...");
});
//观察状态
State state = t.getState();
System.out.println(state); //NEW
t.start();
state = t.getState();
System.out.println(state); //RUNNABLE
while(state != Thread.State.TERMINATED)
{
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = t.getState(); //TIMED_WAITING
System.out.println(state);
}
state = t.getState(); //TERMINATED
System.out.println(state);
}
}
7、优先级
package com.sxt.state;
/**
* 线程的优先级 1-10
* 1、NORM_PRIORITY 5 默认
* 2、MIN_PRIORITY 1
* 3、MAX_PRIORITY 10
*
* 优先级代表概率,不代表绝对的先后顺序(比如一个优先级高的线程yield一下)
*
* @author Jiusen
*
*/
public class Priority
{
public static void main(String[] args)
{
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority()); //5
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);
//设置优先级(在线程启动之前)
t1.setPriority(Thread.MAX_PRIORITY); //范围在1-10之间
t2.setPriority(Thread.MAX_PRIORITY); //范围在1-10之间
t3.setPriority(Thread.MAX_PRIORITY); //范围在1-10之间
t4.setPriority(Thread.MIN_PRIORITY); //范围在1-10之间
t5.setPriority(Thread.MIN_PRIORITY); //范围在1-10之间
t6.setPriority(Thread.MIN_PRIORITY); //范围在1-10之间
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class MyPriority implements Runnable
{
@Override
public void run()
{
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
}
}
8、守护线程
守护线程:是为用户线程服务的:jvm停止不用等待守护线程执行完毕
默认:用户线程: jvm等待用户线程执行完毕才会停止
package com.sxt.state;
/**
* 守护线程:是为用户线程服务的:jvm停止不用等待守护线程执行完毕
*
* 默认:用户线程: jvm等待用户线程执行完毕才会停止
* @author 郭久森
*
*/
public class DaemonTest
{
public static void main(String[] args)
{
Thread t1 = new Thread(new You());
Thread t2 = new Thread(new God());
t1.setDaemon(true); //将用户线程设置为守护
t1.start();
t2.start();
}
}
class You extends Thread
{
@Override
public void run()
{
for(int i=1;i<365*10;i++)
{
System.out.println("happy life...");
}
System.out.println("life over~~~~~~~~");
}
}
class God extends Thread
{
@Override
public void run()
{
for(int i=1;i<365*100;i++)
{
System.out.println("bless you!!!!!!!!!!");
}
}
}
9、基本信息
package com.sxt.state;
/**
* isAlive:线程是否还活着
* Thread.currentThread():当前线程
* setName、getName:代理名称
* @author 郭久森
*
*/
public class InfoTest
{
public static void main(String[] args) throws Exception
{
System.out.println(Thread.currentThread().isAlive());
//设置名称:真是角色 + 代理角色
MyInfo info = new MyInfo("战斗机");
Thread t = new Thread(info);
t.setName("公鸡");
t.start();
Thread.sleep(1000);
System.out.println(t.isAlive());
}
}
class MyInfo implements Runnable
{
private String name;
public MyInfo(String name)
{
this.name = name;
}
@Override
public void run()
{
System.out.println(Thread.currentThread().getName() + "-->" + name);
}
}
10、并发—非同步—三大经典案例
并发
并发:同一个对象多个线程同时操作
/*
* 线程不安全: 数据有负数、相同的情况
*/
public class UnsafeTest01 implements Runnable
{
//票数
private int ticketNums = 10; //共享的资源
private boolean flag = true;
@Override
public void run()
{
while(flag)
{
test();
}
}
public void test()
{
if(ticketNums < 0)
{
flag = false;
}
try {
Thread.sleep(200); //模拟网络卡顿
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
public static void main(String[] args)
{
System.out.println(Thread.currentThread().getName());
//一份资源
UnsafeTest01 web = new UnsafeTest01();
//多个代理
new Thread(web, "森经理").start();
new Thread(web, "莹董事").start();
new Thread(web, "宝宝").start();
}
}
package com.sxt.sychronized;
public class UnsafeTest02
{
public static void main(String[] args)
{
Account account = new Account(100, "结婚礼金");
Drawing you = new Drawing(account, 80, "可悲的你");
Drawing wife = new Drawing(account, 90, "happy的她");
you.start();
wife.start();
}
}
//账户
class Account
{
int money; //金额
String name; //名称
public Account(int money, String name)
{
this.money = money;
this.name = name;
}
}
//模拟取款
class Drawing extends Thread
{
Account account;//取钱的账户
int drawingMoney; //取的钱数
int packetTotal; //口袋的总数
public Drawing(Account account, int drawingMoney, String name)
{
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run()
{
if(account.money - drawingMoney < 0)
{
return;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money - drawingMoney;
packetTotal = packetTotal + drawingMoney;
System.out.println(this.getName() + "-->账户余额为: " + account.money);
System.out.println(this.getName() + "-->口袋里钱为: " + packetTotal);
}
}
package com.sxt.sychronized;
import java.util.ArrayList;
import java.util.List;
/*
* 线程不安全: 数据有负数、相同的情况
*/
public class UnsafeTest3
{
public static void main(String[] args)
{
List<String> list = new ArrayList<>();
for(int i = 0; i < 10000; i++)
{
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
System.out.println(list.size());
}
}
11、并发-同步
11.1、队列与锁
11.2、synchronized方法
package com.sxt.sychronized;
/*
* 线程安全:在并发时保证数据的正确性、效率尽可能高
* synchronied
* 1、同步方法
* 2、同步块
*/
public class UnsafeTest01 implements Runnable
{
//票数
private int ticketNums = 10; //共享的资源
private boolean flag = true;
@Override
public void run()
{
while(flag)
{
test();
}
}
//线程安全 同步(锁this对象资源)
public synchronized void test()
{
if(ticketNums <= 0)
{
flag = false;
return;
}
try {
Thread.sleep(200); //模拟网络卡顿
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
public static void main(String[] args)
{
System.out.println(Thread.currentThread().getName());
//一份资源
UnsafeTest01 web = new UnsafeTest01();
//多个代理
new Thread(web, "森经理").start();
new Thread(web, "莹董事").start();
new Thread(web, "宝宝").start();
}
}
package com.sxt.sychronized;
public class SynchronizedTest02
{
public static void main(String[] args)
{
Account2 account = new Account2(100, "结婚礼金");
Drawing2 you = new Drawing2(account, 80, "可悲的你");
Drawing2 wife = new Drawing2(account, 90, "happy的她");
you.start();
wife.start();
}
}
//账户
class Account2
{
int money; //金额
String name; //名称
public Account2(int money, String name)
{
this.money = money;
this.name = name;
}
}
//模拟取款
class Drawing2 extends Thread
{
Account2 account;//取钱的账户
int drawingMoney; //取的钱数
int packetTotal; //口袋的总数
public Drawing2(Account2 account, int drawingMoney, String name)
{
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run()
{
test();
}
//目标不对,锁定失败,这里不是锁this,应该锁account2
public synchronized void test()
{
if(account.money - drawingMoney < 0)
{
return;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money - drawingMoney;
packetTotal = packetTotal + drawingMoney;
System.out.println(this.getName() + "-->账户余额为: " + account.money);
System.out.println(this.getName() + "-->口袋里钱为: " + packetTotal);
}
}
11.3、synchronized块
package com.sxt.sychronized;
/*
* 线程安全:在并发时保证数据的正确性、效率尽可能高
* synchronied
* 1、同步方法
* 2、同步块:目标更明确
*/
public class SynchronizedBlockTest3
{
public static void main(String[] args)
{
Account3 account = new Account3(100, "结婚礼金");
Drawing3 you = new Drawing3(account, 80, "可悲的你");
Drawing3 wife = new Drawing3(account, 90, "happy的她");
you.start();
wife.start();
}
}
//账户
class Account3
{
int money; //金额
String name; //名称
public Account3(int money, String name)
{
this.money = money;
this.name = name;
}
}
//模拟取款
class Drawing3 extends Thread
{
Account3 account;//取钱的账户
int drawingMoney; //取的钱数
int packetTotal; //口袋的总数
public Drawing3(Account3 account, int drawingMoney, String name)
{
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run()
{
test();
}
//目标锁account3
public synchronized void test()
{
//提高性能
if(account.money <= 0)
{
return;
}
synchronized (account)
{
if(account.money - drawingMoney < 0)
{
return;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money - drawingMoney;
packetTotal = packetTotal + drawingMoney;
System.out.println(this.getName() + "-->账户余额为: " + account.money);
System.out.println(this.getName() + "-->口袋里钱为: " + packetTotal);
}
}
}
package com.sxt.sychronized;
import java.util.ArrayList;
import java.util.List;
/*
* 线程不安全: 数据有负数、相同的情况
*
*/
public class SynchronizedBlock04
{
public static void main(String[] args)
{
List<String> list = new ArrayList<>();
for(int i = 0; i < 10000; i++)
{
new Thread(()->{
synchronized (list) {
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(list.size());
}
}
11.4、性能分析