欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程实战篇(二)

程序员文章站 2022-04-11 08:02:03
...

一:JAVA实现多线程的方式

(|.1)继承Thread类,重写Run方法

package com.mutit.demo.anspan;
/**
 * @author 藤井大叔
 */
public class MyThread extends Thread {

    //1.方法一:继承Thread类,重写run方法
    //1.1编写run方法
    public  void run(){
        System.out.println("111");
    }
    //1.2:编写main方法,运行多线程
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        myThread1.start();
        myThread2.start();
    }
}

(|.2)实现Runable接口,重写Run方法

下面展示一些 内联代码片

package com.mutit.demo.anspan;
import com.mutit.demo.fuill.HelloWord;
/**
 * @author 藤井大叔
 */
public class MyThread extends HelloWord implements Runnable {

    //1.方法二:使用Runnable接口,实现run方法
    //使用Runnable接口是因为java只能单继承,就可以实现Runnable接口
    //1.1编写run方法
    public  void run(){
        System.out.println("这里是run方法");
    }
    //1.2:编写main方法,运行多线程
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
       Thread thread = new Thread(myThread1);
       thread.start();
    }
}

(|.3)使用线程池,添加执行任务

package com.mutit.demo.anspan;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * @author 本章代码摘要
 * https://blog.csdn.net/u011480603/article/details/75332435
 */
public class MyRunnable {
    private static int POOL_NUM = 10;     //线程池数量
    /**
     * 实现方法三:线程池
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for(int i = 0; i<POOL_NUM; i++)
        {
            RunnableThread thread = new RunnableThread();
            executorService.execute(thread);
        }
        //关闭线程池
        executorService.shutdown();
    }
}
class RunnableThread implements Runnable
{
    @Override
    public void run()
    {
        System.out.println("通过线程池方式创建的线程:" + Thread.currentThread().getName() + " ");
    }
}

二:多线程的状态

在大部分人当中都认为线程状态只有五种,但是返过去看看源码状态是有六种,然后今天呢,就把这线程的五种和六种都一一介绍一下
先说一下五种:

线程的五种状态

(1)创建状态
创建状态可以说是你是new一个Thread的时候就开始创建了,但是还没有启动线程中的代码
(2)就绪状态
你在使用的多线程的时候呢,调用start()方法是必要的,当你的线程对象调用start()方法后,也就意味创建了系统资源,当执行run()方法后,返回start()结果,线程也就处于就绪状态了
(3)运行状态
当线程进入CPU时间后,也就是说明这个线程的运行状态开始了
(4)阻塞状态
阻塞状态是指某种原因放弃了CPU的使用权,暂时停止运行
阻塞状态也分几种:
1.等待阻塞
2.同步阻塞
3.其他阻塞
(5)死亡状态
main方法或者Run()执行结束,也可能是某种异常导致的结束,当执行结束后说明该线程也是结束了整个生命周期,死亡的多线程是不可再生

状态图

多线程实战篇(二)

线程的六种状态

多线程实战篇(二)
下面我再来说一说多线程的六种状态,也就是在源码上所显示的
所谓的六种状态分别是以下几种
(1)初始化
新创建了一个线程对象,但还没有调用start()方法
(2)可运行
Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)
(3)阻塞
表示线程阻塞于锁
(4)等待
进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)
(5)超时等待
该状态不同于WAITING,它可以在指定的时间后自行返回
(6)终止
表示该线程已经执行完

状态图

多线程实战篇(二)

测试状态转换

package com.mutit.demo.pojo;

public class ThreadStateTest {
    public static Object lock = new Object();

    public static void main(String[] args) {
        System.out.println("==================================  线程状态测试开始 ==================================");
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread thread = Thread.currentThread();
                String tname = thread.getName();
                System.out.println("【Thread】:" + tname + "is running ---------> state : " + thread.getState());
                try {
                    Thread.sleep(1000); // 当前线程休眠1秒
                    //LockSupport.parkNanos(1000*1000*1000);
                } catch (Exception e){
                    e.printStackTrace();
                }
                long start = System.currentTimeMillis();
                for (int i = 0; i < 1500000000L; i++) {
                    ; // 循环模拟执行业务
                }
                long end = System.currentTimeMillis();
                System.out.println("【Thread】:" + tname + "循环耗时:" + (end - start) + "ms");
                synchronized (lock) {
                    try {
                        lock.wait(1000); // 当前线程等待1秒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                synchronized (lock) {
                    try {
                        lock.wait(); // 当前线程一直等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("【Thread】" + tname + " wait over ----------> state : " + thread.getState());
                }
            }
        }, "t1");
        System.out.println("【Main】new Thread() ------------> state : " + t1.getState());
        // 启动线程再看
        t1.start();
        System.out.println("【Main】t1.start() --------------> state : " + t1.getState());

        try {
            Thread.sleep(500);
            // 主线程休眠0.5秒,查看t1线程状态
            System.out.println("【Main】t1 sleep(1000) ----------> state : " + t1.getState());
            Thread.sleep(800);
            System.out.println("【Main】t1 for  -----------------> state : " + t1.getState());

            Thread.sleep(1000);
            System.out.println("【Main】t1 wait(1000)  ----------> state : " + t1.getState());

            Thread.sleep(1000);
            synchronized (lock) {
                System.out.println("【Main】t1 wait()  --------------> state : " + t1.getState());
                lock.notify();
                System.out.println("【Main】lock notify()  ----------> state : " + t1.getState());
                Thread.sleep(1000);
                System.out.println("【Main】no exit sync-block ------> state : " + t1.getState());
            }
            Thread.sleep(10);
            System.out.println("【Main】t1 over  ----------------> state : " + t1.getState());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

三:终止线程的方法

stop方法(不安全,不推荐使用)

这种方法现在是差不多用不着了,也是不推荐进行使用了,因为不安全,它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在

package com.mutit.demo.pojo;

public class StopThreadTest {
    public static class SellTicket implements Runnable {
        int count = 2; // 剩余票数
        int selled = 0;      // 已经卖出票数
        @Override
        public void run() {
            synchronized (this){
                count--;
                try {
                    Thread.sleep(1000); // 模拟买票延迟
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                selled++;
            }
        }
        public void print(){
            System.out.println("剩余票数 = " + count + ", 卖出票数 = " + selled);
        }
    }
    public static void main(String[] args) {
        SellTicket sellTicket = new SellTicket();
        Thread t1 = new Thread(sellTicket);
        Thread t2 = new Thread(sellTicket);
        t1.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.stop();

        t2.start();
        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sellTicket.print();
    }
}

interrupt方法

interrupt()方法不像stop方法强行终止一个线程。它只是把要被停止的线程设置成中断状态。而此时要被中断的线程是可以继续执行的

package com.mutit.demo.pojo;

public class StopThreadTest {
    public static class SellTicket implements Runnable {
        int count = 2; // 剩余票数
        int selled = 0;      // 已经卖出票数
        @Override
        public void run() {
            synchronized (this){
                count--;
                try {
                    Thread.sleep(1000); // 模拟买票延迟
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                selled++;
            }
        }
        public void print(){
            System.out.println("剩余票数 = " + count + ", 卖出票数 = " + selled);
        }
    }
    
    public static void main(String[] args) {
        SellTicket sellTicket = new SellTicket();
        Thread t1 = new Thread(sellTicket);
        Thread t2 = new Thread(sellTicket);
        t1.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //t1.stop();
        /*
         * 用interrupt方法能通过抛出InterruptedException中断阻塞状态
         * 避免stop方法直接结束进程导致的数据不一致
         */
        t1.interrupt();
        t2.start();
        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sellTicket.print();
    }
}

使用标志退出

使用标志位终止线程就是定义一个boolean型的标志位 ,在线程的run方法中根据这个标志位是为true还是为false来判断是否终止,这种情况多用于while循环中

package com.mutit.demo.pojo;

public class StopThread extends Thread {
    private boolean flag = true;
    @Override
    public synchronized void run() {
        while (flag) {
            System.out.println(Thread.currentThread().getName()+"---我是子线程");
        }
    }
    public void stopThread() {
        flag = false;
        System.out.println(getName()+"线程被终止掉了");
    }

    public static void main(String[] args) {
        StopThread stopThread1 = new StopThread();
        StopThread stopThread2 = new StopThread();
        stopThread1.start();
        stopThread2.start();
        for (int i = 0; i < 50; i++) {
            System.out.println("------我是主线程-----"+i);
            if(i==30) {
                stopThread1.stopThread();
                stopThread2.stopThread();
            }
        }
    }
}
相关标签: java 后端