Java多线程学习笔记

线程简介

Process(进程)和Thread(线程)

进程:执行程序的一次执行过程,他是一个动态概念,是系统资源分配的单位

线程就是独立的执行路径

在程序运行式,即使没有自己创建线程,后台也会有多个线程

main称之为主线程,为系统的入口,用于执行整个程序

在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度是与操作系统紧密相关的,先后顺序式不能人为的干预的

对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制

线程会带来额外的开销,如cpu调度实践,并发控制开销

每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

进程---->线程(默认线程 main线程 gc线程)

线程创建

Thread class:继承Thread类

Runnable接口:实现Runnable接口

Callable接口:实现Callable接口

继承Thread类:

子类继承Thread类具备多线程能力

启动线程:子类对象.start()

不建议使用:避免OOP单继承局限性

实现Runnable接口

实现接口Runnable具有多线程能力

启动线程:传入目标对象+Thread对象.start()

推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

实现Callable 接口

1.实现Callable接口,需要返回值类型

2.重写call方法,需要抛出异常

3.创建目标对象

4.创建执行服务:ExecutorService ser =Executors.newFixedThreadPool(1)

5.提交执行:Future result1=ser.submit(t1);

6.获取结果:boolean r1=result1.get();

7.关闭服务:ser.shutdownNow();

Lambda表达式

避免匿名内部类定义过多

其实质为面向函数式编程

函数式接口是学习Lambda表达式的重点

任何一个接口如果只包含唯一一个抽象方法,那么他就是一个函数式接口

多余函数式接口,我们可以使用Lambda表达式实现接口

简化过程:实体类—>静态内部类---->局部内部类---->匿名内部类---->Lambda简化

package com.kuang.demo02;

/**
 * @Package: com.kuang.demo02
 * @ClassName: TestLamda1
 * @Author: adim
 * @CreateTime: 2020/8/11 16:23
 * @Description:推到Lambda表达式
 */
public class TestLamda1 {
    //3.静态内部类
    static class Like2 implements ILike{

        @Override
        public void lambda() {
            System.out.println("i like lambda2");
        }
    }
    //1.定义一个函数式接口
    public static void main(String[] args) {
        ILike like=new Like();
        like.lambda();
        ILike like2=new Like2();
        like2.lambda();
        //4.局部内部类
        class Like3 implements ILike{

            @Override
            public void lambda() {
                System.out.println("i like lambda3");
            }
        }
        like=new Like3();
        like.lambda();
        //5.匿名内部类,没有类的名称,必须借助接口或者父类实现
        like=new ILike() {
            @Override
            public void lambda() {
                System.out.println("i like lambda4");

            }
        };
        like.lambda();
        //6.用lambda简化
        like=()-> {
            System.out.println("i like lambda5");
        };
        like.lambda();
    }
}
interface ILike{
    void lambda();
}

//2.实现类
class Like implements  ILike{

    @Override
    public void lambda() {
        System.out.println("i like lambda");
    }
}
package com.kuang.demo02;

import java.util.List;

/**
 * @Package: com.kuang.demo02
 * @ClassName: TestLambda2
 * @Author: adim
 * @CreateTime: 2020/8/11 16:33
 * @Description:
 */
public class TestLambda2 {
    static class Love2 implements ILove{

        @Override
        public void love(int a) {
            System.out.println(a);
        }
    }
    public static void main(String[] args) {
        ILove iLove=new Love();
        iLove.love(1);
        Love2 love2=new Love2();
        love2.love(2);
        ILove love3= new  ILove(){

            @Override
            public void love(int a) {
                System.out.println(a);
            }
        };
        love3.love(3);
        //lambda简化
        //简化一:去除参数类型
        ILove love4=(a)->{
            System.out.println(a);
        };
        //简化括号:
        love4=a->{
            System.out.println(a);
        };
        //简化三:去除花括号
        love4=a-> System.out.println("i love" +a);
        //总结:若想去除花括号,代码必须只有一行,
        /*
        * lambda只能有一行代码的情况下,才能简化成为一行,如果有多行,那么只能由代码块包括
        * 2.前提是接口为函数式接口
        *3.多个参数也可以去除参数类型,但是要去掉必须同时去掉
        * */
        love4.love(5);
    }
}
interface ILove{
    void love(int a);
}
class Love implements ILove{

    @Override
    public void love(int a) {
        System.out.println(a);
    }
}

线程实现(重点)

线程五大状态

创建状态:

就绪状态

运行状态

阻塞状态

死亡状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mn6UhqBV-1597666025660)(C:\Users\adim\AppData\Roaming\Typora\typora-user-images\image-20200812093024022.png)]

setPriority :

sleep:

join:

yield

isAlive

线程停止:推荐使用一个标志位进行终止变量,当flag=false,则线程终止运行

package com.kuang.state;

/**
 * @Package: com.kuang.state
 * @ClassName: TestTop
 * @Author: adim
 * @CreateTime: 2020/8/12 9:34
 * @Description:建议使用线程正常停止,利用次数不建议死循环,建议使用标志位
 * 2.不要使用stop或destory等过时或者JDK不建议使用的方法
 */
public class TestTop implements Runnable{
    private boolean falg=true;
    @Override
    public void run() {
        int i=0;
        while(falg){
            System.out.println("run ... Thread"+i++);
        }
    }
    public void stop(){
        this.falg=false;
    }

    public static void main(String[] args) {
        TestTop testTop=new TestTop();
        new Thread(testTop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if(i==900){
                testTop.stop();
                System.out.println("线程停止了");
            }
        }
    }
}

线程休眠:

sleep(时间)指定当前线程阻塞的毫秒数

sleeep存在异常InterruptedException

sleep时间达到后线程进入就绪状态

sleep可以模拟网络延时,倒计时等

每一个对象都有一个锁,sleep不会释放锁

package com.kuang.state;

import java.beans.SimpleBeanInfo;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Package: com.kuang.state
 * @ClassName: TestSleep2
 * @Author: adim
 * @CreateTime: 2020/8/12 9:42
 * @Description:模拟倒计时,打印系统时间
 */
public class TestSleep2 {
    public static void main(String[] args) {
        Date startTime=new Date(System.currentTimeMillis());
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime=new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
    //模拟倒计时
    public void tenDown() throws InterruptedException {
        int num=10;
        while (true){
            Thread.sleep(1000);
            System.out.println(num--);
            if(num<0){
                break;
            }
        }
    }
}

线程礼让

礼让线程,让当前正在执行的线程暂停,但不阻塞

将现场从运行状态转为就绪状态

让cpu重新调度,但是礼让可能不成功

package com.kuang.state;

/**
 * @Package: com.kuang.state
 * @ClassName: TestYied
 * @Author: adim
 * @CreateTime: 2020/8/12 9:48
 * @Description:测试礼让线程,礼让不一定成功,看CPU心情
 */
public class TestYied {
    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();//礼让
        System.out.println("停止执行"+Thread.currentThread().getName());
    }
}

join:

join合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞

package com.kuang.state;

/**
 * @Package: com.kuang.state
 * @ClassName: TestJoin
 * @Author: adim
 * @CreateTime: 2020/8/12 10:01
 * @Description:测试join方法
 */
public class TestJoin implements Runnable{

    @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 < 1000; i++) {
            if(i==200){
                    thread.join();
            }
            System.out.println("main"+i);
        }
    }
}

线程状态观测:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x3CMrdrv-1597666025664)(C:\Users\adim\AppData\Roaming\Typora\typora-user-images\image-20200812100732579.png)]

package com.kuang.state;

import java.util.SortedMap;

/**
 * @Package: com.kuang.state
 * @ClassName: TestState
 * @Author: adim
 * @CreateTime: 2020/8/12 10:08
 * @Description:
 */
public class TestState {
    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);
        }
    }
}

线程优先级:

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行

使用getPriority获取优先级,使用setProiority来修改优先级

守护线程(damon)

线程分为用户现场和守护线程

虚拟机必须保证用户线程执行完毕

虚拟机不用等待守护线程执行完毕

如,后台级联操作日志,监控内存,垃圾回收等待。。。

package com.kuang.state;

import sun.awt.windows.ThemeReader;

/**
 * @Package: com.kuang.state
 * @ClassName: TestDaemon
 * @Author: adim
 * @CreateTime: 2020/8/12 10:45
 * @Description:测试守护线程
 */
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);
        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("goodbye world=====");
    }
}
class  God implements Runnable{

    @Override
    public void run() {
        while(true){
            System.out.println("shangdibaoyouzheni");
        }
    }
}

线程同步(重点)

多个线程操作同一个资源

并发:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZPDAldEW-1597666025666)(C:\Users\adim\AppData\Roaming\Typora\typora-user-images\image-20200812105435706.png)]

三大不安全案例

package com.kuang.syn;

import java.util.ArrayList;
import java.util.List;

/**
 * @Package: com.kuang.syn
 * @ClassName: UnsafeList
 * @Author: adim
 * @CreateTime: 2020/8/12 11:22
 * @Description:线程不安全的集合
 */
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>() ;
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                list.add(Thread.currentThread().getName());
            }).start();
        }
        System.out.println(list.size());
    }
}
package com.kuang.syn;

/**
 * @Package: com.kuang.syn
 * @ClassName: UnsafeBank
 * @Author: adim
 * @CreateTime: 2020/8/12 11:08
 * @Description:不安全的取钱
 */
public class UnsafeBank {
    public static void main(String[] args) {
        Account account=new Account(100,"基金");
        Bank bank=new Bank(account,60,"你");
        Bank bank1=new Bank(account,60,"你的妻子");
        bank.start();
        bank1.start();
    }
}
class  Account{
    int money;

    String name;

    public Account(int money,String name) {
        this.name=name;
        this.money=money;
    }
}
class  Bank extends Thread{
    Account account;
    int drawingMoney;
    int nowMoney;
    public Bank(Account account,int drawingMoney,String name){
        super(name);
        this.account=account;
        this.drawingMoney=drawingMoney;
    }
    @Override
    public void run(){

        if(account.money-drawingMoney<=0){
            System.out.println(Thread.currentThread().getName()+"钱不够取不了");
            return;
        }
        //sleep可以放大问题的发生性
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money=account.money-drawingMoney;
        nowMoney=drawingMoney;
        System.out.println(account.name+"余额"+account.money);
        System.out.println(this.getName()+"手里的钱"+nowMoney);
    }
}

package com.kuang.syn;

import javax.management.relation.RoleUnresolved;

/**
 * @Package: com.kuang.syn
 * @ClassName: UnsafeBuyTicket
 * @Author: adim
 * @CreateTime: 2020/8/12 11:01
 * @Description:线程不安全
 */
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        safeBuyTicket safeBuyTicket=new safeBuyTicket();
        new Thread(safeBuyTicket,"1").start();
        new Thread(safeBuyTicket,"2").start();
        new Thread(safeBuyTicket,"3").start();
    }

}
class  safeBuyTicket implements Runnable{
    private int ticketNums=10;
    private boolean falg=true;
    @Override
    public void run() {
        while(falg){
            buy();
        }
    }

    public void buy(){

        if(ticketNums<=0){
            return;
        }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--+"张票");

    }
}

结局方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmEdemWU-1597666025668)(C:\Users\adim\AppData\Roaming\Typora\typora-user-images\image-20200812155354114.png)]

死锁

各个线程各自站有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形,摸一个同步块同时拥有两个以上的对象的锁就会产生死锁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nh4HRq31-1597666025670)(C:\Users\adim\AppData\Roaming\Typora\typora-user-images\image-20200812165830400.png)]

线程通信问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uRJ5lIGJ-1597666025671)(C:\Users\adim\AppData\Roaming\Typora\typora-user-images\image-20200812214606326.png)]

高级主题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值