Java教程

JAVA多线程笔记

本文主要是介绍JAVA多线程笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JAVA多线程

线程创建

1.Thread类

  1. 自定义线程类继承Thread类

  2. 重写run()方法,编写线程执行体

  3. 创建线程对象,调用start()方法启动线程

//创建线程方式一:继承Thread类 重写run()方法,调用start开启线程
public class TestThread1 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) {
        
        //创建一个线程对象
        TestThread1 testThread1 = new TestThread1();
        //调用start()方法开启线程(交替执行)
        testThread1.start();
        //调用run()方法先执行run()再执行主方法
        //testThread1.run();
        for (int i = 0; i < 20; i++) {
            System.out.println("我在执行多线程"+i);
        }
​
    }
}
​
/*注意!线程开启不一定立即执行,由CPU调度执行*/

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

  1. 定义MyRunnable类实现Runnable接口

  2. 实现run()方法,编写线程执行体

  3. 创建线程对象,调用start()方法启动线程

//创建线程方式2:实现runnable接口,重写run方法,执行线程需要丢入runnable类接口实现类,调用start方法
public class TestThread3 implements Runnable{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码"+i);
        }
    }
​
    public static void main(String[] args) {
        //创建runnable接口的实现类对象
        TestThread3 testThread3 = new TestThread3();
        //创建线程对象,通过线程对象来开启我们的线程
        Thread thread = new Thread(testThread3);
​
        thread.start();
​
        //简写 newThread(testThread3).start();
​
        for (int i = 0; i < 20; i++) {
            System.out.println("我在执行多线程"+i);
        }
​
    }
}

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

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

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

  3. 创建目标对象

  4. 创建执行服务

ExecutorService ser = Executors.newFixedThreadPool(1);
  1. 提交执行

Future<Boolean>result1 = ser.submit(t1);
  1. 获取结果

boolean r1 = result.get()
  1. 关闭服务

ser.shutdownNow();

/*图片下载案例 callable方法实现*/
​
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
​
/**
 * TODO
 *
 * @author wlj
 * @version 1.0
 * @Description
 * @date 2022/1/15 16:39
 */
​
/*
callable的好处
可以抛出异常
具有返回值
 */
​
//线程创建方式三:实现callable接口
public class TestCallable implements Callable<Boolean> {
    private String url;//网络图片地址
    private String name;//保存的文件名
​
    public TestCallable(String url, String name) {
        this.url = url;
        this.name = name;
    }
​
​
    @Override
    public Boolean call() {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println("下载了文件名为:" + name);
        return true;
    }
​
    public static void main(String[] args) throws ExecutionException, InterruptedException {
​
​
        TestCallable testThread1 = new TestCallable("https://webstatic.mihoyo.com/upload/puzzle/2021/12/22/1a4f9ac397162af7b11616ea7acb5115_4472408160447119381.png", "1.jpg");
        TestCallable testThread2 = new TestCallable("https://webstatic.mihoyo.com/upload/puzzle/2021/12/22/1a4f9ac397162af7b11616ea7acb5115_4472408160447119381.png", "2.jpg");
        TestCallable testThread3 = new TestCallable("https://webstatic.mihoyo.com/upload/puzzle/2021/12/22/1a4f9ac397162af7b11616ea7acb5115_4472408160447119381.png", "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();
/*====================================================================*/ 
    }
}
​
​
//下载器
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. sleep(时间)指定当前线程阻塞的毫秒数

  2. sleep存在异常InterruptedException

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

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

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

//模拟倒计时
public class TestSleep2 {
    public static void main(String[] args) {
//        try {
//            tenDown();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
​
        //打印当前时间
        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 static void tenDown() throws InterruptedException{
        int num = 10;
        while (true) {
            Thread.sleep(1000);
            System.out.println(num--);
            if(num<=0){
                break;
            }
        }
    }
}

线程关闭

  1. 不推荐使用JDK提供的stop(),destory()方法【已废弃】

  2. 推荐线程自己停止下来

  3. 建议使用一个标志位进行终止变量,当flag = false,则终止线程运行

//测试stop
    //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 testStop = new TestStop();

        new Thread(testStop).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if(i == 900){
                //调用自己写的stop方法切换标志位,让线程停止
                testStop.stop();
            }
        }
    }
}

线程礼让

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

  2. 将线程从运行状态转为就绪状态

  3. 让CPU重新调度,礼让不一定成功

//测试礼让线程
    //礼让不一定成功,看CPU心情
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();//礼让
        System.out.println(Thread.currentThread().getName()+"线程停止执行");
    }
}

线程强制执行

//测试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 < 500; i++) {
            if(i == 200){
                thread.join();//插队
            }
            System.out.println("main"+i);
        }
    }
}

线程状态观察

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); //NEW

        //观察启动后
        thread.start();//启动线程
        state = thread.getState();
        System.out.println(state);//Run

        while(state != Thread.State.TERMINATED){//只要线程不终止 就一直输出状态
            Thread.sleep(100);
            state = thread.getState();//更新线程状态
            System.out.println(state);//打印线程状态
        }
    }
}

线程优先级

线程的优先级用数字表示,范围从1~10

  1. Thread.MIN_PRIORITY = 1;

  2. Thread.MAX_PRIORITY = 10;

  3. Thread.NORM_PRIORITY = 5;

使用以下方式改变或获取优先级

  1. getPriority()

  2. setPriority(int xxx)

public class TestPriority {
​
    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
​
        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.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
​
    }
}
​
class MyPriority implements Runnable{
​
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}

守护线程

  1. 线程分为用户线程和守护线程

  2. 虚拟机必须确保用户线程执行完毕

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

  4. 如:后台记录操作日志,监控内存,垃圾回收等待

//测试守护线程
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 God implements  Runnable{
    @Override
    public void run() {
        while(true){
            System.out.println("上帝保佑你");
        }
    }
}
​
//你
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("你一生都开心地活着");
        }
        System.out.println("-====goodbye! world!====-");
    }
}
​

这篇关于JAVA多线程笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!