1.并发编程---线程基础的概念

什么是线程与进程

进程:类似于电脑打开的QQ、酷我音乐、腾讯影视等软件
线程:在看电视的时候听歌并且聊天都属于线程完成的

并发与并行

并发:单位时间内可以执行的请求次数
并行:在某一时刻可以执行的请求次数

多线程实现的三种方式

  • 继承Thread类,重写run方法
  • 实现Runable接口,重写run方法
  • 实现Callable接口,重写call方法

实现方式1

package ms.studyjava.threads.demo1;

import lombok.SneakyThrows;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * 创建线程的三种方式
 *
 * **/
public class NewThread {

    public static void main(String[] args) throws Exception {
        NewThread newThread = new NewThread();
        newThread.getThread();
        newThread.getRunable();
        newThread.getFuture();
    }

    public void getThread(){
        ThreadMethods threadMethods = new ThreadMethods();
        threadMethods.setName("Thread线程名称");
        threadMethods.start();
    }
    public void getRunable(){
        RunableMethods runableMethods = new RunableMethods();
        //创建Thread对象。对象调用start启动线程
        Thread thread = new Thread(runableMethods,"runable线程名称");
        thread.start();
    }
    public void getFuture() throws ExecutionException, InterruptedException {
        CallableMethods callableMethods = new CallableMethods();
        //将实现Callable接口的类的对象,丢进FutureTask构造方法中得到新的FutureTask对象,在创建Thread对象调用satrt方法启动线程
        FutureTask<String> stringFutureTask = new FutureTask<>(callableMethods);
        Thread thread = new Thread(stringFutureTask,"callabel线程名称");
        thread.start();
        //等待线程结束进行返回值接受
        while (true){
            if (stringFutureTask.isDone()){
                System.out.println(stringFutureTask.get());
                break;
            }
        }
    }
}

/**
 *
 * 继承Thread,重写Run方法
 * **/
class ThreadMethods extends Thread{
    @SneakyThrows
    @Override
    public void run() {
        System.out.println("-----------Thrad-------------");
        System.out.println(Thread.currentThread().getName());
        System.out.println("----------Thrad--------------");
    }
}
/**
 *  * 实现Runable接口,重写Run方法
 * **/
class RunableMethods implements Runnable{
    @Override
    public void run() {
        System.out.println("----------Runable--------------");
        System.out.println(Thread.currentThread().getName());
        System.out.println("----------Runable--------------");
    }
}
/**
 *  * 实现Callable接口重写call接口
 * **/
class CallableMethods implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("----------Callable--------------");
        System.out.println(Thread.currentThread().getName());
        System.out.println("----------Callable--------------");
        return "调用callable返回的值";
    }
}

实现方式2

package com.ms.study.demo.thread;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @ClassName: RunableThread
 * @Description:
 */
public class CreateThread {
    public void createthread(){
        new Thread(){
            @Override
            public void run() {
                System.out.println("启动Thread线程");
            }
        }.start();
    }

    public void createRubale(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("启动Runable线程");
            }
        };
        new Thread(runnable).start();
    }

    public Object createCallable() throws ExecutionException, InterruptedException {
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call()  {
                System.out.println("启动callable线程");
                return "callable线程返回值";
            }
        };
        FutureTask<String> taskFuture = new FutureTask<String>(callable);
        new Thread(taskFuture).start();
        return taskFuture.get();
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CreateThread runableThread = new CreateThread();
        runableThread.createthread();
        runableThread.createRubale();
        Object callable = runableThread.createCallable();
        System.out.println(callable);
    }
}

可以轻易的发现,不管你用那种方式实现线程,最终都是需要通过new Thread().statr()方法进行线程启动

怎么让线程安全停止

  • 安全执行结束
  • 抛出异常
  • interrupt线程中断。来源于Thread里面一个方法,用于中断线程。该方法相当于给当前线程一个提示,提示该线程需要进行中断,至于是否一定中断,完全取决于该线程自己

使用interrupt中断线程

1.正常的中断线程

class ThreadStopMethods extends Thread {
    @Override
    public void run() {
        //判断当前线程是否被中断,没有中断就继续执行业务。返回true表示已中断
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println(Thread.currentThread().getName() + "未被中断,正在执行业务.....");
        }
        //线程已经被中断时候打印
        System.out.println(Thread.currentThread().getName() + "中断状态:" + Thread.currentThread().isInterrupted());
    }
}
 /**
     * 线程安全停止的方法
     */
    public void safeStop() throws InterruptedException {
        ThreadStopMethods thread = new ThreadStopMethods();
        //1.interrupt。来源于Thread里面一个方法,用于中断线程
        //该方法相当于给当前线程一个提示,提示该线程需要进行中断,至于是否一定中断,完全取决于该线程自己
        thread.setName("interrupt中断线程---");
        thread.start();
        //让主线程睡眠一段时间
        Thread.sleep(3000);
        //中断线程
        thread.interrupt();
    }
interrupt中断线程---未被中断,正在执行业务.....
interrupt中断线程---未被中断,正在执行业务.....
interrupt中断线程---未被中断,正在执行业务.....
interrupt中断线程---未被中断,正在执行业务.....
interrupt中断线程---中断状态:true

2.抛出InterruptedException 异常情况,线程中断的标志会一直被复位成false。需要自己在线程的try-catch中手动的中断
会发现一旦抛出InterruptedException异常后,中断状态将一直都是复位成false的,也就是说一直无限循环执行下去

class ThreadStopMethods extends Thread {
    @Override
    public void run() {
        //判断当前线程是否被中断,没有中断就继续执行业务。返回true表示已中断
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"--抛出InterruptedException异常,中断状态:"+Thread.currentThread().isInterrupted());
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
        System.out.println(Thread.currentThread().getName() + "已被中断,中断状态:" + Thread.currentThread().isInterrupted());
    }
}
interrupt中断线程---
interrupt中断线程---
interrupt中断线程-----抛出InterruptedException异常,中断状态:false
interrupt中断线程---
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at ms.studyjava.threads.demo1.ThreadStopMethods.run(NewThread.java:74)
interrupt中断线程---
interrupt中断线程---
interrupt中断线程---
interrupt中断线程---
......无限循环.......

出现这种情况就需要我们在线程里面再次手动的中断线程。避免线程一直在执行

class ThreadStopMethods extends Thread {
    @Override
    public void run() {
        //判断当前线程是否被中断,没有中断就继续执行业务。返回true表示已中断
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"--抛出InterruptedException异常,中断状态:"+Thread.currentThread().isInterrupted());
                //再次手动中断线程
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
        System.out.println(Thread.currentThread().getName() + "已被中断,中断状态:" + Thread.currentThread().isInterrupted());
    }
}
interrupt中断线程---
interrupt中断线程---
interrupt中断线程---
interrupt中断线程---
interrupt中断线程---
interrupt中断线程-----抛出InterruptedException异常,中断状态:false
interrupt中断线程---
interrupt中断线程---已被中断,中断状态:true
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at ms.studyjava.threads.demo1.ThreadStopMethods.run(NewThread.java:74)

线程状态

在这里插入图片描述
Sleep方法
将线程从运行状态变成阻塞状态。举个例子:比如你在公司用微波炉热饭,热到一半发现自己有急事要出去一趟,这时候你把饭拿走,等事情处理完后在进行热饭,在你走的这段时间微波炉可能已经被他人使用,你再次回来就需要排队使用了。
yield方法(用的较少)
将线程从运行状态变成可运行状态,举个例子:你在公司正在用微波炉热饭,这时候看到你好朋友都一起来了,于是你把饭拿出来,说大家一起抢下,谁速度快就就热饭,这个时候你可能还可以继续热饭。也就是说,yield的线程,可能再次继续被执行。
run和statr方法理解
run是启动一个线程。start是将创建的线程放入就绪装备等待run方法执行

/**
 * run和start
 * **/
class RunStatrMethods extends Thread{
    @Override
    public void run() {
        System.out.println("线程名称:"+Thread.currentThread().getName());
    }
}
  public void runStatr(){
        RunStatrMethods thread = new RunStatrMethods();
        thread.setName("RunStatrMethods线程");
        //直接调用run方法
        thread.run();
        //调用start
        //thread.start();
    }
线程名称:main

发现直接调用run方法,打印的线程名称居然是main,这是为什么呢?再看下调用start结果

线程名称:main
线程名称:RunStatrMethods线程

很惊讶的方法run和statr都执行RunStatrMethods 里面的run方法了。但是结果却不一样。
解释:Main方法的是一个单独的线程,在调用run方法之前,这里面没有其他线程调用start进行启动。所以RunStatrMethods .run()实际上是main函数的线程去调用了Thread里面的run方法,当start启动了RunStatrMethods 线程时候,这时候才有RunStatrMethods 线程自己去调用Thread里面的run方法,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值