前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程的基本方法

线程的基本方法

作者头像
晚上没宵夜
发布2020-03-10 09:18:19
4310
发布2020-03-10 09:18:19
举报
文章被收录于专栏:Howl同学的学习笔记

1. 进程与线程

进程:资源分配的基本单位

线程:资源调度的基本单位

1.1 有了进程为什么还需要线程呢?

为了进程能进行并发操作

1.2 线程的生命周期

2. 创建进程

创建进程有两种方法(一般推荐第二种,因为单继承问题)

先来看看线程的构造函数
2.1 继承Thread类,重写run()
代码语言:javascript
复制
public class Threadtest extends Thread {
    
    //设置名字
    public Threadtest(String name) {
        super(name);
    }
    
    //重写方法
    public void run(){
        for(int i = 0;i < 100;i++){
            System.out.println(Thread.currentThread().getName() + "-----" + i);
        }
    }
    
    public static void main(String[] args) {
        
        Threadtest t1 = new Threadtest("线程1");
        Threadtest t2 = new Threadtest("线程2");
        
        t1.start();
        t2.start();
    }
}
2.2 实现Runnable接口,重写run()
代码语言:javascript
复制
public class Runnabletest implements Runnable {
    
    @Override
    public void run() {
        for(int i = 0;i < 100;i++){
            System.out.println(Thread.currentThread().getName() + ":::" + i);
        }
    }
    
    public static void main(String[] args) {
        
        Thread t1 = new Thread(new Runnabletest(),"线程1");
        Thread t2 = new Thread(new Runnabletest(),"线程2");
        
        t1.start();
        t2.start();
    }
}
代码语言:javascript
复制
// 上面两种方法都是线程交替进行
线程1:::0
线程1:::1
线程1:::2
线程1:::3
线程1:::4
线程2:::0
线程1:::5
线程1:::6
线程1:::7
线程1:::8
线程1:::9
线程1:::10
线程2:::1

3.线程的方法

3.1 命名 getName()
  • 该构造函数里的init方法的第三个参数是线程名
  • 第三个参数是个函数,该函数同步地维护了threadInitNumber,是一个数字
  • 可想而知,线程名字是 Thread-Number,eg: Thread-0
  • 从2.1/2.2可知构造方法里面提供了命名线程的方式
代码语言:javascript
复制
/**
 * Allocates a new {@code Thread} object. This constructor has the same
 * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 * {@code (null, null, gname)}, where {@code gname} is a newly generated
 * name. Automatically generated names are of the form
 * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 */
public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

/* For autonumbering anonymous threads. */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
    return threadInitNumber++;
}
  • 也可以通过 setName(String name) 来命名,不过该方法调用native方法,笔者水平有限不做深究
代码语言:javascript
复制
Thread thread = new Thread(() -> {
    System.out.println(Thread.currentThread().getName());
});
thread.setName("新线程名");
代码语言:javascript
复制
新线程名
3.1 守护线程(setDaemon)
  • 守护进程是为其他线程服务的线程,存在于后台,一旦有线程就存在,线程全部消失而结束,eg: 垃圾回收线程
  • 守护线程中产生的新线程也是守护线程
  • 需要在进程启动前调用Thread.setDaemon(true),会用native方法检测,非法则抛出异常
代码语言:javascript
复制
public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;    //设置守护线程为真
}

/* Whether or not the thread is a daemon thread. */
// private boolean  daemon = false;
3.2 优先级(setPriority)
  • 设置获取CPU时间片的几率,分0—10等级,默认为5
代码语言:javascript
复制
// MAX_PRIORITY 最大级别10
// MIN_PRIORITY 最小0
// NORM_PRIORITY 普通5

public final void setPriority(int newPriority) {
    ThreadGroup g;  //线程组
    checkAccess();
    if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
        throw new IllegalArgumentException();
    }
    if((g = getThreadGroup()) != null) {
        if (newPriority > g.getMaxPriority()) {
            newPriority = g.getMaxPriority();
        }
        setPriority0(priority = newPriority);  //设置级别,后面遇到native方法不说明了
    }
}
代码语言:javascript
复制
public static void main(String[] args) {
        
        Threadtest t1 = new Threadtest("线程1");
        Threadtest t2 = new Threadtest("线程2");
    
        //设置优先级
        t1.setPriority(10);
        
        t1.start();
        t2.start();
}
代码语言:javascript
复制
线程1:::97
线程1:::98
线程1:::99
线程2:::3
线程2:::4
线程2:::5

在前面实例中调用该函数,发现t1线程cpu执行时间片多于t2线程,t1完成了t2还在开头

3.3 sleep
  • 让该线程休眠,不释放锁
  • 结束重回就绪状态
  • t1.sleep(),不是t1睡眠,而是当前线程睡眠
  • 哪个线程调用sleep方法,哪个线程就睡眠
代码语言:javascript
复制
public class Threadtest extends Thread {
    
    //设置名字
    public Threadtest(String name) {
        super(name);
    }

    //重写方法
    public void run(){
        for(int i=0; i < 100;i++){
            System.out.println(Thread.currentThread().getName() + "--" + i);
        }
        
    }
    
    public static void main(String[] args) throws InterruptedException {
        Threadtest t2 = new Threadtest("线程2");

        t2.start();
        t2.sleep(10000);
        
        System.out.println("=========");
    }
}
代码语言:javascript
复制
线程2--96
线程2--97
线程2--98
线程2--99
//10秒后,main线程睡眠
=======
3.4 join
  • 使当前线程停下来等待,直到调用join()的线程结束,才恢复执行
  • 它可以使得线程之间的并行执行变为串行执行
  • 在start之后才执行的
  • 底层还是调用wait方法
代码语言:javascript
复制
public class Threadtest extends Thread {
    
    //设置名字
    public Threadtest(String name) {
        super(name);
    }

    //重写方法
    public void run(){
        for(int i=0; i < 100;i++){
            System.out.println(Thread.currentThread().getName() + "--" + i);
        }
        
    }
    
    public static void main(String[] args) throws InterruptedException {
        
        Threadtest t1 = new Threadtest("线程1");
        Threadtest t2 = new Threadtest("线程2");

        t2.setPriority(10);
        t1.start();
        t1.join();      //main线程停下来,等t1执行完才继续往下执行,所以先输入t1,再输出t2
        t2.start();
    }
}
3.5 wait和notify
  • wait使当前线程挂起,notify随机唤醒一个同享对象锁的线程,notifyAll唤醒所有
  • wait必须在同步代码块或同步方法中调用,先要有锁才能释放锁
  • wait方法释放锁,并处于阻塞状态
  • notify不是立即释放锁,要执行完同步操作才释放锁
  • 被其他线程唤醒后处于就绪状态
代码语言:javascript
复制
thread.wait();
thread.notify();
3.6 yield

使当前线程从运行状态转为就绪状态,即可能让别的线程执行,也可能自己再次执行

3.7 interrupt
  • 该方法不是即时中断线程,而是仅仅设置一个中断信号量,然后中断操作由我们自己实现
代码语言:javascript
复制
Thread t1 = new Thread(new Runnable(()->{
    // 若未发生中断,就正常执行任务
    while(!Thread.currentThread.isInterrupted()){
        // 正常任务代码……
    }
    // 中断的处理代码……
    doSomething();
}).start();
  • 当线程在活动之前或活动期间处于阻塞状态(正在等待、休眠或占用状态)且该线程被中断时,抛出InterruptedException
  • 阻塞线程调用interrupt()方法,会抛出异常,设置标志位为false,同时该线程会退出阻塞
3.8 exit

退出当前线程(或者当run方法结束也是线程结束)

3.9 start和run区别
  • run():仅仅是封装被线程执行的代码,直接调用是普通方法
  • start():创建线程,jvm调用线程的run()方法,所以start方法执行完,不代表run方法执行完,线程也不一定销毁!
3.10 currentThread()

获取当先运行的线程,Thread thread = Thread.currentThread(),属于静态方法

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-12-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 进程与线程
    • 1.1 有了进程为什么还需要线程呢?
      • 1.2 线程的生命周期
        • 先来看看线程的构造函数
        • 2.1 继承Thread类,重写run()
        • 2.2 实现Runnable接口,重写run()
        • 3.1 命名 getName()
        • 3.1 守护线程(setDaemon)
        • 3.2 优先级(setPriority)
        • 3.3 sleep
        • 3.4 join
        • 3.5 wait和notify
        • 3.6 yield
        • 3.7 interrupt
        • 3.8 exit
        • 3.9 start和run区别
        • 3.10 currentThread()
    • 2. 创建进程
    • 3.线程的方法
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档