首页 > 编程语言 > 详细

Java多线程基础(待续...)

时间:2021-08-16 10:32:08      阅读:17      评论:0      收藏:0      [点我收藏+]

线程简介

程序进程线程

程序指令数据有序集合静态概念

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

线程独立执行的路径(运行程序时,即使没有创建线程后台会有多个线程,主线程,gc线程)

注意:真正的多线程是有多个CPU(多核),如服务器。模拟多线程优于切换速度很快,就会有多线程的错觉

线程实现(重点)

三种创建方式

  1. Thread class(继承Thread类)

  2. Runnable接口(实现Runnable接口)

  3. Callable接口(实现Callable接口)

注意线程开启不一定执行,由CPU调度

Thread class

  1. 创建类继承自Thread类

  2. 重写run()方法

  3. 调用start()方法开启线程

public class TestThread1 extends Thread {
    @Override
    public void run() {
        // run方法体
    }

    public static void main(String[] args) {
        
        TestThread1 t1 = new TestThread1();
        // 调用start()方法
        t1.start();
    }
}

Runnable(推荐使用)

  1. 声明类实现Runnable接口

  2. 重写run()方法

  3. 创建类对象

  4. 创建Thread时作为参数传递,调用start()方法

public class TestThread3 implements Runnable{
    @Override
    public void run() {
        // run方法体
    }

    public static void main(String[] args) {
        // 创建一个线程对象
        TestThread3 t3 = new TestThread3();

        // 线程丢入Thread类,调用start方法
        new Thread(t3).start();
    }
}

龟兔赛跑 - Race

静态代理

StaticProxy静态代理,Runnable实现的原理

public class StaticProxy {
    public static void main(String[] args) {
        // 创建对象,相当于创建实现了Runnable接口的对象
        You y1 = new You();
        // 相当于将对象传入Thread类并调用start方法
        new WeddingCompany(y1).HappyMarry();
        
        //可简写为:    new WeddingCompany(new You()).HappyMarry();
    }
}

// marry接口,相当于Runnable接口
interface Marry{
    void HappyMarry();
}

// You类,相当于实现Runnable接口的类
class You implements Marry {
    @Override
    public void HappyMarry(){
        System.out.println("你要结婚了");
    }
}

// 代理角色,帮助你结婚,相当于Thread类
class WeddingCompany implements Marry{
	
    private Marry target;
    
    // 传入you对象,相当于有参构造Thread类
    public WeddingCompany(Marry target){
        this.target = target;
    }
    // 具体的实现细节,相当于重写Run方法
    @Override
    public void HappyMarry(){
        before();
        this.target.HappyMarry();
        after();
    }

    private void after() {
        System.out.println("结婚后,补尾款");
    }

    private void before() {
        System.out.println("结婚前,布置现场");
    }
}

lambda表达式在接口中的使用

函数式接口:只包含一个抽象方法的接口

lambda表达式在函数式接口中的使用:类名 对象名 = (参数类型 形参名) -> { 需要重写的语句块; };

简化重写方法的部分代码

可简化的部分

  1. 参数类型

  2. 括号

  3. 花括号

public class Test {
    public static void main(String[] args) {

        Person person = (int a)-> {System.out.println("person eat" + a);};
        
        // 1.  (a)-> {System.out.println("person eat" + a);};
        
        // 2.  a-> {System.out.println("person eat" + a);};
        
        // 3.  a-> System.out.println("person eat" + a);
        person.eat(1);
        
    }
}


interface Person{
    void eat(int a);
}

Callable

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

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

  3. 创建目标对象

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

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

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

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

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

public class TestCallable implements Callable<Boolean> {
    private String url;
    private String name;

    public TestCallable(String url, String name){
        this.name = name;
        this.url = url;
    }

    @Override
    public Boolean call() {
        // 创建 WebDownloader 对象
        WebDownloader webDownloader = new WebDownloader();
        // 调用downloader方法,传入
        webDownloader.downloader(url,name);
        System.out.println("下载了文件名为:" + name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 新建对象并传参 url,name
        TestCallable t1 = new TestCallable("https://img2020.cnblogs.com/blog/2459624/202107/2459624-20210728230730532-2056940147.png","1.png");
        TestCallable t2 = new TestCallable("https://img2020.cnblogs.com/blog/2459624/202107/2459624-20210728203411378-1829797592.png", "2.png");
        TestCallable t3 = new TestCallable("https://img2020.cnblogs.com/blog/2459624/202107/2459624-20210728203430153-280296762.png","3.png");

        // 创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);

        // 提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        // 获取结果

        boolean rs1 = r1.get();
        boolean rs2 = r2.get();
        boolean rs3 = r3.get();

        // 关闭服务
        ser.shutdownNow();

    }
}


// 下载器
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方法出现问题");
        }
    }

}

线程状态

线程五大状态

  • 创建状态

  • 就绪状态

  • 阻塞状态

  • 运行状态

  • 死亡状态

线程停止:设置一个标志位,通过公开的方法转换标志位

//1.建议线程正常停止-->利用次数,不建议死循环
//2.建议使用标志位--->设置一个标志位
//3.不要使用stop或者destroy等过时或JDK不建议使用的方法

public class TestStop implements Runnable{

    //1.设置一个标志位
    private boolean flag = true;

    @Override
    public void run(){
        int i = 0;
        while (flag){
            System.out.println("run...Thread" + i++);
        }
    }

    //2.设置一公开方法停止线程,转换标志位
    public void stop() {
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop ts1 = new TestStop();

        new Thread(ts1).start();

        for (int i = 0; i < 200; i++) {
            System.out.println("main" + i);
            if (i==50){
                ts1.stop();
                System.out.println("Thread线程停止了");
            }
        }
    }

}

线程休眠sleep方法

// 模拟倒计时
// 打印系统当前时间

Thread.sleep(1000);//参数为毫秒

线程礼让yield方法

Thread.currentThread().getName():获取当前线程的name

//测试礼让线程
// 礼让不一定成功,看CPU心情
public class TestYield {
    public static void main(String[] args) {
        MyYield my1 = new MyYield();

        new Thread(my1,"a").start();
        new Thread(my1,"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方法

public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 500; i++) {
            System.out.println("vip线程来到了"+i);
        }
    }

    public static void main(String[] args) throws InterruptedException{

        TestJoin tj1 = new TestJoin();
        
        Thread thread = new Thread(tj1);
        
        thread.start();

        // 主线程
        for (int i = 0; i < 250; i++) {
            if (i == 200) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println("主线程"+i);

        }
    }
    
}

注意:在调用join方法前,线程是同步执行的,调用join方法后其他方法进入阻塞状态

线程同步(重点)

线程通信问题

高级主体

Java多线程基础(待续...)

原文:https://www.cnblogs.com/Coline1/p/15145777.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!