一,创建多线程的方式
1.创建多线程方式一(不是很推荐用,局限性较大)
创建线程方式一
1.继承Thread+重写run
2.创建子类对象+start
public class test01 extends Thread {
//线程入口点
public void run() {
for(int i=0;i<5;i++){
System.out.println("一边看综艺");
}
}
public static void main(String[] args) {
//启动
test01 t=new test01();
t.start();
for(int i=0;i<5;i++){
System.out.println("一边吃泡面");
}
}
}
2.创建多线程方式二
创建多线程方式二
1.实现Runnable+重写run
2.创建实现类对象+Thread对象+start
public class test02 implements Runnable{
public void run() {
for(int i=0;i<5;i++){
System.out.println("一边看综艺");
}
}
public static void main(String[] args) {
//创建实现类对象
test01 t1=new test01();
//创建代理类对象
Thread t2=new Thread(t1);
//启动
t2.start();
for(int i=0;i<5;i++){
System.out.println("一边吃泡面");
}
}
}
3.创建多线程方式三(了解即可)
import java.util.concurrent.*;
public class CDownload implements Callable {
private String url;
private String name;
public CDownload(String url, String name) {
super();
this.url=url;
this.name=name;
}
@Override
public Boolean call() throws Exception {
WebDownload wd=new WebDownload();
wd.download(url,name);
System.out.println(name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
CDownload td1=new CDownload("http://5b0988e595225.cdn.sohucs.com/images/20190603/f035172f209b4cc0aec85d14399534b4.jpeg","fcc1.jpeg");
CDownload td2=new CDownload("http://5b0988e595225.cdn.sohucs.com/images/20190603/2ca832285f50430ab356dd118cfe93d7.jpeg","fcc2.jpeg");
CDownload td3=new CDownload("http://5b0988e595225.cdn.sohucs.com/images/20190603/f2d45fa8ce074a3e88b6a6f46caa6827.jpeg","fcc3.jpeg");
new Thread((Runnable) td1).start();
new Thread((Runnable) td2).start();
new Thread((Runnable) td3).start();
//创建执行服务
ExecutorService ser= Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> result1=ser.submit(td1);
Future<Boolean> result2=ser.submit(td2);
Future<Boolean> result3=ser.submit(td3);
//获取结果
boolean r1=result1.get();
boolean r2=result2.get();
boolean r3=result3.get();
//关闭服务
ser.shutdownNow();
}
}
二,多线程的底层实现方式-------静态代理
* 静态代理
* 1.真实角色实现接口
* 2.代理角色实现接口
/**
* 静态代理
* 1.真实角色
* 2.代理角色
*/
public class StaticProxy {
public static void main(String[] args) {
new WeddingCompany(new You()).HappyMarry();
}
}
//结婚接口
interface Marry{
void HappyMarry();
}
//真实角色实现接口
class You implements Marry{
public void HappyMarry() {
System.out.println("有情人终成眷属");
}
}
//代理角色
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target){
this.target=target;
}
public void HappyMarry() {
ready();
this.target.HappyMarry();
after();
}
private void ready(){
System.out.println("布置婚房...");
}
private void after(){
System.out.println("闹洞房...");
}
}
三,简化线程的使用-----Lambda表达式
1.用几种常见的类调用同一个方法,进行比较
public class LambdaTest01 {
//静态内部类
static class Like1 implements ILike{
@Override
public void lambda() {
System.out.println("I like English1");
}
}
public static void main(String[] args) {
ILike like=new Like();
like.lambda();
like=new Like1();
like.lambda();
class Like2 implements ILike{
//局部内部类
@Override
public void lambda() {
System.out.println("I like English2");
}
}
like=new Like2();
like.lambda();
//匿名内部类
like=new ILike(){
public void lambda() {
System.out.println("I like English3");
}
};
like.lambda();
//lambda表达式
like=()-> {
System.out.println("I like English4");
};
like.lambda();
}
}
//接口
interface ILike{
void lambda();
}
//普通类
class Like implements ILike{
public void lambda() {
System.out.println("I like English");
}
}
2.lambda表达式的优越,以及其简化形式
(1)正常形式
无参数无返回值
like=()-> {
System.out.println("I like English4");
};
有参数无返回值
MD myd=(String s)->{
System.out.println("My idol is-->"+s);
};
有参数有返回值
ADD a=(int b1,int b)->{
System.out.println("结果为"+(b1+b));
return b1+b;
};
(2)简化形式
无参数无返回值,只有一句语句时可简化为
like=()-> System.out.println("I like English4");
有参数无返回值时,可将返回值类型省略,括号省略(只有一句语句花括号可以省略,其他情况不可省略)
myd=s-> System.out.println("My idol is-->"+s);
有参数有返回值时
ADD a=(b1,b)->{
System.out.println("结果为"+(b1+b));
return b1+b;
};
有参数有返回值且只有一个返回语句时
a=(b1,b)-> b1+b;
(3)各种lambda形式比较
//有参数的方法
public class LambdaTest02 {
public static void main(String[] args) {
MD myd=(String s)->{
System.out.println("My idol is-->"+s);
};
myd.md("范丞丞和宋亚轩");
//简化
myd=(s)->{
System.out.println("My idol is-->"+s);
};
myd.md("福西西和宋芽芽");
//再次简化
myd=s->{
System.out.println("My idol is-->"+s);
};
myd.md("范泽言和宋村村");
//再次简化(只有一行代码是可这样)
myd=s-> System.out.println("My idol is-->"+s);
myd.md("大白鹅和小漂亮");
}
}
interface MD{
void md(String s);
}
public class LambdaTest03 {
public static void main(String[] args) {
ADD a=(int b1,int b)->{
System.out.println("结果为"+(b1+b));
return b1+b;
};
//有参数时可简化为
a=(b1,b)->{
System.out.println("结果为"+(b1+b));
return b1+b;
};
a.add(3,12);
//如果只有一个return语句时,可简化为
a=(b1,b)-> b1+b;
System.out.println(a.add(120,20));
}
}
interface ADD{
int add(int b1,int b);
}
四,线程的几种状态
1.尚未启动的线程的状态:NEW
2.在java虚拟机中执行的线程的状态:RUNNABLE
3.被阻塞等待监视器锁定的线程的状态:BLOCKED
4.正在等待另一个线程执行特定动作的线程的状态:WAITING
5.正在等待另一个线程执行动作达到指定等待时间的线程的状态:TIMED_WAITING
6.已退出的线程的状态:TERMINATED
import javax.swing.plaf.nimbus.State;
public class AllStste {
public static void main(String[] args) {
Thread t=new Thread(()->{
for(int i=0;i<10;i++) {
try {
Thread.sleep(100);//TIMED_WAITING
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("......");
}
});
Thread.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();
System.out.println(state);
}
}
}
五,线程的优先级
* 线程的优先级 1-10
* 1.NORM_PRIORITY 默认5
* 2.MIN_PRIORITY 1
* 3.MAX_PRIORITY 10
* 优先级高的不一定先执行,只是执行的概率比较大
public class PriorityTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getPriority());
MyPriority mp=new MyPriority();
Thread t1=new Thread(mp,"1");
Thread t2=new Thread(mp,"2");
Thread t3=new Thread(mp,"3");
Thread t4=new Thread(mp,"4");
Thread t5=new Thread(mp,"5");
Thread t6=new Thread(mp,"6");
t1.setPriority(Thread.NORM_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t3.setPriority(Thread.MIN_PRIORITY);
t4.setPriority(Thread.MAX_PRIORITY);
t5.setPriority(Thread.MAX_PRIORITY);
t6.setPriority(Thread.MAX_PRIORITY);
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());
}
}
六,守护线程
* 守护线程:是为用户线程服务的;jvm停止不用等待守护线程执行完毕
* jvm停止需要等待用户线程执行完毕
* 默认为用户线程
public class DaemonTest {
public static void main(String[] args) {
Person p=new Person();
God god=new God();
new Thread(p).start();
Thread t=new Thread(god);
t.setDaemon(true);
t.start();
}
}
class Person implements Runnable{
@Override
public void run() {
for(int i=0;i<100*365;i++){
System.out.println("天天开心");
}
System.out.println("############");
}
}
class God implements Runnable{
@Override
public void run() {
while(true){
System.out.println("保佑你");
}
}
}
七,一些其他的线程常用方法
* isAlive:线程是否还活着
* Thread.currentThread():当前线程
* setName getName:设置和获得代理名称
public class InfoTest {
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().isAlive());
MyInfo mi=new MyInfo("小甜豆");
Thread t=new Thread(mi);
t.setName("人间");
t.start();
Thread.sleep(200);
System.out.println(t.isAlive());
}
}
class MyInfo implements Runnable{
private String name;
public MyInfo(String name){
this.name=name;
}
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+name);
}
}
八,多线程的并发
1.不安全线程的改进
(1)买票问题
* 线程不安全(买票)
* 1.同一张票被多个人买到
* 2.没票了,却还是有人买到
import sun.misc.Unsafe;
public class UnsafeTest01 {
public static void main(String[] args) {
UnsafeWeb12306 web=new UnsafeWeb12306();
new Thread(web,"一级").start();
new Thread(web,"二级").start();
new Thread(web,"三级").start();
}
}
class UnsafeWeb12306 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;
return;
}
else{
try {
Thread.sleep(100);
System.out.print(Thread.currentThread().getName()+TicketNums--+"\t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
出现以下不安全的情况:
二级2 一级1 三级1 二级0 三级-1 一级-1
* 线程安全
* 运用synchronized
public class SafeTest01 {
public static void main(String[] args) {
SafeWeb12306 web=new SafeWeb12306();
new Thread(web,"一级").start();
new Thread(web,"二级").start();
new Thread(web,"三级").start();
}
}
class SafeWeb12306 implements Runnable {
private int TicketNums = 10;
private boolean flag=true;
@Override
public void run() {
while (flag) {
test();
}
}
public synchronized void test(){
if (TicketNums <=0) {
flag = false;
return;
}
else{
try {
Thread.sleep(100);
System.out.print(Thread.currentThread().getName()+TicketNums--+"\t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(2)取钱问题
* 线程不安全(取钱)
* 账户余额不足也能取出钱
public class UnsafeTest02 {
public static void main(String[] args) {
Account account=new Account(1000,"奖金");
Drawing I=new Drawing(account,700,"我");
Drawing YOU=new Drawing(account,800,"你");
Drawing HE=new Drawing(account,800,"他");
Drawing SHE=new Drawing(account,800,"她");
Drawing THEM=new Drawing(account,800,"他们");
new Thread(I).start();
new Thread(YOU).start();
new Thread(HE).start();
new Thread(SHE).start();
new Thread(THEM).start();
}
}
class Account{
int money;
String name;
public Account(int money,String name){
this.money=money;
this.name=name;
}
}
class Drawing implements Runnable{
Account account;//账户
int drawingMoney;//取的钱数
int packetMoney;//取的总数
String name1;
public Drawing(Account account, int drawingMoney,String name1){
this.name1=name1;
this.drawingMoney=drawingMoney;
this.account=account;
}
public void run() {
if(account.money-drawingMoney<0){
return;
}
else{
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money-=drawingMoney;
packetMoney+=drawingMoney;
System.out.println(account.name+"账户余额为:"+account.money);
System.out.println(this.name1+"取出的总额为:"+packetMoney);
}
}
}
出现的问题:
奖金账户余额为:-600
奖金账户余额为:-600
奖金账户余额为:-600
奖金账户余额为:-1400
他们取出的总额为:800
他取出的总额为:800
她取出的总额为:800
奖金账户余额为:-600
我取出的总额为:700
你取出的总额为:800
* 线程安全
* 运用synchronized块
public class SafeTest02 {
public static void main(String[] args) {
Account account=new Account(1000,"奖金");
SafeDrawing I=new SafeDrawing(account,700,"我");
SafeDrawing YOU=new SafeDrawing(account,800,"你");
SafeDrawing HE=new SafeDrawing(account,800,"他");
SafeDrawing SHE=new SafeDrawing(account,800,"她");
SafeDrawing THEM=new SafeDrawing(account,800,"他们");
new Thread(I).start();
new Thread(YOU).start();
new Thread(HE).start();
new Thread(SHE).start();
new Thread(THEM).start();
}
}
class SafeDrawing implements Runnable{
Account account;//账户
int drawingMoney;//取的钱数
int packetMoney;//取的总数
String name1;
public SafeDrawing(Account account, int drawingMoney,String name1){
this.name1=name1;
this.drawingMoney=drawingMoney;
this.account=account;
}
public void run() {
test();
}
public void test() {
synchronized (account) {
if (account.money - drawingMoney < 0) {
return;
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money -= drawingMoney;
packetMoney += drawingMoney;
System.out.println(account.name + "账户余额为:" + account.money);
System.out.println(this.name1 + "取出的总额为:" + packetMoney);
}
}
}
}
(3)容器问题
* 线程不安全:(容器)
* 不能将需要放入容器的内容全部放入容器中
public class unsafeTest03 {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<>();
for(int i=0;i<1000;i++){
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(2000);
System.out.println(list.size());
}
}
输出结果:
994
* 线程安全
* 运用synchronized块
import java.util.ArrayList;
import java.util.List;
public class SafeTest03 {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<>();
for(int i=0;i<1000;i++){
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(2000);
System.out.println(list.size());
}
}
2.安全线程性能优化
(1)买票问题
public class SynBlockTest01 {
public static void main(String[] args) {
SynWeb12306 web=new SynWeb12306();
new Thread(web,"一级").start();
new Thread(web,"二级").start();
new Thread(web,"三级").start();
}
}
class SynWeb12306 implements Runnable {
private int TicketNums = 10;
private boolean flag=true;
@Override
public void run() {
while (flag) {
test();
}
}
public synchronized void test(){
if (TicketNums <=0) {
flag = false;//考虑没有票的情况
return;
}
synchronized (this) {
if (TicketNums <= 0) {
flag = false;//考虑最后一张票
return;
} else {
try {
Thread.sleep(100);
System.out.print(Thread.currentThread().getName() + TicketNums-- + "\t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
(2)取钱问题
public class SynBlockTest02 {
public static void main(String[] args) {
Account account=new Account(1000,"奖金");
SynDrawing I=new SynDrawing(account,700,"我");
SynDrawing YOU=new SynDrawing(account,800,"你");
SynDrawing HE=new SynDrawing(account,800,"他");
SynDrawing SHE=new SynDrawing(account,800,"她");
SynDrawing THEM=new SynDrawing(account,800,"他们");
new Thread(I).start();
new Thread(YOU).start();
new Thread(HE).start();
new Thread(SHE).start();
new Thread(THEM).start();
}
}
class SynDrawing implements Runnable{
Account account;//账户
int drawingMoney;//取的钱数
int packetMoney;//取的总数
String name1;
public SynDrawing(Account account, int drawingMoney,String name1){
this.name1=name1;
this.drawingMoney=drawingMoney;
this.account=account;
}
public void run() {
test();
}
public void test() {
if(account.money<0){
return;
}
synchronized (account) {
if (account.money - drawingMoney < 0) {
return;
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money -= drawingMoney;
packetMoney += drawingMoney;
System.out.println(account.name + "账户余额为:" + account.money);
System.out.println(this.name1 + "取出的总额为:" + packetMoney);
}
}
}
}
3.安全线程的应用(电影院选票)
import java.util.ArrayList;
import java.util.List;
public class HappyCinema {
public static void main(String[] args) {
List<Integer> available=new ArrayList<>();
available.add(1);
available.add(3);
available.add(5);
available.add(6);
available.add(9);
List<Integer> l1=new ArrayList<>();
l1.add(1);
l1.add(3);
List<Integer> l2=new ArrayList<>();
l2.add(9);
Cinema c=new Cinema(available,"奥斯卡");
new Thread(new Customer(c,l1),"yy").start();
new Thread(new Customer(c,l2),"cc").start();
}
}
class Customer implements Runnable{
Cinema cinema;
List<Integer> seats;
public Customer(Cinema cinema, List<Integer> seats){
this.cinema=cinema;
this.seats=seats;
}
public void run() {
synchronized (cinema) {
boolean flag = cinema.bookTickets(seats);
if (flag) {
System.out.println("出票成功" + Thread.currentThread().getName() + "->位置为:" + seats);
} else {
System.out.println("出票失败" + Thread.currentThread().getName() + "->没有位置");
}
}
}
}
class Cinema{
List<Integer> available;
String name;
public Cinema(List<Integer> available,String name){
this.available=available;
this.name=name;
}
//购票
public boolean bookTickets(List<Integer> seats){
System.out.println("可用位置为:" + available);
List<Integer> copy=new ArrayList<>();
copy.addAll(available);
copy.removeAll(seats);
if(available.size()-copy.size()!=seats.size()){
return false;
}
available=copy;
return true;
}
}
七,死锁的发生
* 死锁:过多的同步可能造成相互不释放资源
* 从而相互等待,一般发生于同步中持有多个对象的锁
* 为避免死锁,不要在同一个代码块中,同时持有多个对象的锁
public class DeadLock {
public static void main(String[] args) {
Makeup g1=new Makeup(1,"枫子张");
Makeup g2=new Makeup(0,"娜娜");
g1.start();
g2.start();
}
}
class Lipstick{
}
class Mirror{
}
class Makeup extends Thread{
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();
//选择
int choice;
//名字
String girl;
public Makeup(int choice,String girl){
this.choice=choice;
this.girl=girl;
}
@Override
public void run() {
//化妆
Makeup();
}
private void Makeup(){
if(choice==0){
synchronized (lipstick){
System.out.println(this.girl+"涂口红");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){
System.out.println(this.girl+"照镜子"); }
}
}
else{
synchronized (mirror){
System.out.println(this.girl+"照镜子");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){
System.out.println(this.girl+"涂口红");}
}
}
}
}
八,并发协作(消费者,生产者模式)
1.管程法
* 协作模型:生产者消费者
* 实现方式一:管程法
public class CoTest01 {
public static void main(String[] args) {
SynContainer container=new SynContainer();
Productor p=new Productor(container);
p.start();
Consumer c=new Consumer(container);
c.start();
}
}
//生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container) {
this.container = container;
}
public void run() {
//生产
for(int i=1;i<100;i++){
System.out.println("生产-->"+i+"个馒头");
container.push(new Steamedbun(i));
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
public void run() {
for(int i=1;i<100;i++){
System.out.println("消费-->"+container.pop().id+"个馒头");
}
}
}
//缓冲区
class SynContainer{
Steamedbun[] buns=new Steamedbun[10];//存储容器
int count=1;
//存储生产
public synchronized void push(Steamedbun bun){
//何时生产,容器中有空间时生产
if(count==buns.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buns[count]=bun;
this.notifyAll();
count++;
}
//获取
public synchronized Steamedbun pop(){
//何时消费,容器中存在数据时消费
if(count==1){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
Steamedbun bun=buns[count];
this.notifyAll();
return bun;
}
}
//馒头
class Steamedbun{
int id;
public Steamedbun(int id) {
this.id = id;
}
}
2.信号灯法
* 协作模型:生产者与消费者
* 方式二:信号灯法
* 借助标志位
public class CoTest02 {
public static void main(String[] args) {
TV tv=new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
//生产者 演员
//消费者 观众
//同一个资源 电视
class TV{
String voice;
//信号灯
//T表示演员表演 观众等待
//F表示观众观看 演员等待
boolean flag=true;
//表演
public synchronized void play(String voice){
//演员等待
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("表演了"+voice);
this.voice=voice;
//唤醒
this.notifyAll();
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;
}
}
//生产者 演员
class Player extends Thread{
TV tv;
public Player(TV tv){
this.tv=tv;
}
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;
}
public void run() {
for(int i=0;i<20;i++){
tv.watch();
}
}
}