多线程

一、 实现线程的方式

在JAVA中,创建线程就是创建Thread类(子类)的对象(实例)

java.lang.Thread

Constructor and Description

Thread()

分配一个新的 Thread对象。

Thread(Runnable target)

分配一个新的 Thread对象。 

1. 继承Thread类

例如:

复制代码
class ThreadTest extends Thread{
    public void run(){
        System.out.println("这个线程开始运行");
    }
}
public class Test {
    public static void main(String[] args) {
        ThreadTest tt = new ThreadTest ();
        tt.start();    //启动一个线程
    }
}
复制代码

2. 实现Runnable接口(优先使用)

复制代码
class ThreadTest implements Runnable{
    public void run(){
        System.out.println("这个线程开始运行");
    }
}
public class Test {
    public static void main(String[] args) {
        ThreadTest tt = new ThreadTest ();
        Thread t = new Thread(tt);
        t.start();       //通过一个线程对象启动它
    }
}
复制代码

这两种方式的区别:

1、继承Thread类:编写简单,可直接操作线程。适用于单继承

2、实现Runnable接口:避免单继承局限性,便于共享资源。

推荐使用实现Runnable接口方式创建线程

3. 实现Callable接口(了解)

复制代码
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
//创建Callable接口实现类,并实现call()方法,此方法为线程执行体,且有返回值
class CallableThreadTest implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("执行线程");
        return 1;
    }
}
public class Test {
    public static void main(String[] args) {
        //使用FutureTask类(实现了Future和Runnable接口)来包装Callable对象
        FutureTask<Integer> ft = new FutureTask<>(new CallableThreadTest());
        //使用FutureTask对象作为Thread对象的target创建并启动新线程
        new Thread(ft).start();
        //调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
        try {
            System.out.println("子线程的返回值:" + ft.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

Runnable和Callable的区别:

  1. Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
  2. Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
  3. call方法可以抛出异常,run方法不可以。
  4. 运行Callable任务可以拿到一个Future对象。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

二、 线程的生命周期

  • [NEW]新建状态
    尚未启动的线程处于此状态。新创建了一个线程对象,但未调用start方法
  • [RUNNABLE]就绪状态,即可运行状态,复合状态
    包含ready和running两个状态
    ready:表示该线程处于可被调度调度的状态
    运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
    Thread.yield()方法可以将线程由Running状态变为ready 状态
  • [BLOCKED]阻塞状态
    被阻塞等待监视器锁定的线程处于此状态。
    线程发起I/O操作或者申请由其他线程独占的资源,不占用CPU
    当阻塞I/O执行完毕可或者获得了申请的资源,状态就变为RUNNABLE

阻塞I/O是指,进程会一直阻塞,直到数据拷贝完成;阻塞I/O模式时最普遍使用的I/O模式,如输入、输出、接受连接等

  • [WAITING]
    正在等待另一个线程执行特定动作的线程处于此状态。
    线程执行了object.wait() 或thread.join()方法就会把线程转换为等待状态,执行object.notify()方法或者加入的线程执行完毕,线程将重回RUNNABLE状态

(傻傻的等)

  • [TIMED_WAITING]
    正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
    与WAITING的区别是不会无限期的等待,而是等待指定时间后不管期望的操作是否执行完毕,线程都将重回RUNNABLE状态

(只等等指定长度的时间)

  • [TERMINATED]终止状态
    已退出的线程处于此状态。

三、 线程调度的常用方法

 

方法

功能

getName()

setName()

设置或获取当前线程名称

isAlive()

判断线程是否存活(就绪、运行、阻塞是存活状态)

getPriority()

获取线程优先级

setPriority()

设置线程优先级

Thread.sleep()

强迫线程睡眠(单位:毫秒)(不释放同步锁)

join()

等待某线程结束,再恢复当前线程的运行

yield()

让出CPU资源,当前线程进入就绪状态

wait()

当前线程进入等待状态,即进入等待池。(释放同步锁,由notify()唤醒)

notify()

notifyAll()

唤醒等待池中的某个或全部等待线程 

 

 

posted @   joyfulest  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示