线程的常用方法汇总

1、获取当前线程

使用Thread的静态方法获取当前线程对象

public static void main(String[] args) throws ExecutionException, InterruptedException {
	// 获取当前线程的方法
    Thread main = Thread.currentThread();
    System.out.println(main);
    // "Thread[" + getName() + "," + getPriority() + "," +  group.getName() + "]";
    // Thread[main,5,main]
}

2、设置以及获取线程名称

通常我们都会为线程设置一个有意义的名称,方便后期排查错误

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Thread t1 = new Thread(() -> {
        System.out.println(Thread.currentThread().getName());
    });
    t1.setName("模块-功能-计数器");
    t1.start();
}

3、线程的优先级

其实就是CPU调度线程的优先级、

java中给线程设置的优先级别有10个级别,从1~10任取一个整数。

如果超出这个范围,会排除参数异常的错误

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 1000; i++) {
            System.out.println("t1:" + i);
        }
    });
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 1000; i++) {
            System.out.println("t2:" + i);
        }
    });
    t1.setPriority(1);
    t2.setPriority(10);
    t2.start();
    t1.start();
}

4 、线程的让步

可以通过Thread的静态方法yield,让当前线程从运行状态转变为就绪状态。

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 1000; i++) {
            System.out.println("t1:" + i);
        }
    });
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 1000; i++) {
            System.out.println("t2:" + i);
        }
    });
    t1.setPriority(1);
    t2.setPriority(10);
    t2.start();
    t1.start();
}

5 、线程的休眠

Thread的静态方法,让线程从运行状态转变为等待状态

sleep有两个方法重载:

  • 第一个就是native修饰的,让线程转为等待状态的效果

  • 第二个是可以传入毫秒和一个纳秒的方法(如果纳秒值大于等于0.5毫秒,就给休眠的毫秒值+1。如果传入的毫秒值是0,纳秒值不为0,就休眠1毫秒)

sleep会抛出一个InterruptedException

public static void main(String[] args) throws InterruptedException {
    System.out.println(System.currentTimeMillis());
    Thread.sleep(1000);
    System.out.println(System.currentTimeMillis());
}

6、 线程的强占

Thread的非静态方法join方法

需要在某一个线程下去调用这个方法

如果在main线程中调用了t1.join(),那么main线程会进入到等待状态,需要等待t1线程全部执行完毕,在恢复到就绪状态等待CPU调度。

如果在main线程中调用了t1.join(2000),那么main线程会进入到等待状态,需要等待t1执行2s后,在恢复到就绪状态等待CPU调度。如果在等待期间,t1已经结束了,那么main线程自动变为就绪状态等待CPU调度。

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            System.out.println("t1:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t1.start();
    for (int i = 0; i < 10; i++) {
        System.out.println("main:" + i);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (i == 1){
            try {
                t1.join(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

7、 守护线程

默认情况下,线程都是非守护线程

JVM会在程序中没有非守护线程时,结束掉当前JVM

主线程默认是非守护线程,如果主线程执行结束,需要查看当前JVM内是否还有非守护线程,如果没有JVM直接停止

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            System.out.println("t1:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t1.setDaemon(true);
    t1.start();
}

8、 线程的等待和唤醒

可以让获取synchronized锁资源的线程通过wait方法进去到锁的等待池,并且会释放锁资源

可以让获取synchronized锁资源的线程,通过notify或者notifyAll方法,将等待池中的线程唤醒,添加到锁池

notify随机的唤醒等待池中的一个线程到锁池

notifyAll将等待池中的全部线程都唤醒,并且添加到锁池

在调用wait方法和notify以及norifyAll方法时,必须在synchronized修饰的代码块或者方法内部才可以,因为要操作基于某个对象的锁的信息维护。

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        sync();
    },"t1");
​
    Thread t2 = new Thread(() -> {
        sync();
    },"t2");
    t1.start();
    t2.start();
    Thread.sleep(12000);
    synchronized (MiTest.class) {
        MiTest.class.notifyAll();
    }
}
​
public static synchronized void sync()  {
    try {
        for (int i = 0; i < 10; i++) {
            if(i == 5) {
                MiTest.class.wait();
            }
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName());
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

9、线程的结束方式

线程结束方式很多,最常用就是让线程的run方法结束,无论是return结束,还是抛出异常结束,都可以

9.1 stop方法(不用)

强制让线程结束,无论你在干嘛,不推荐使用,但是他确实可以把线程干掉

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    t1.start();
    Thread.sleep(500);
    t1.stop();
    System.out.println(t1.getState());
}

9.2、使用共享变量(很少会用)

这种方式用的也不多,有的线程可能会通过死循环来保证一直运行。

咱们可以通过修改共享变量在破坏死循环,让线程退出循环,结束run方法

static volatile boolean flag = true;
​
public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        while(flag){
            // 处理任务
        }
        System.out.println("任务结束");
    });
    t1.start();
    Thread.sleep(500);
    flag = false;
}

9.3 interrupt方式

共享变量方式

public static void main(String[] args) throws InterruptedException {
    // 线程默认情况下,    interrupt标记位:false
    System.out.println(Thread.currentThread().isInterrupted());
    // 执行interrupt之后,再次查看打断信息
    Thread.currentThread().interrupt();
    // interrupt标记位:ture
    System.out.println(Thread.currentThread().isInterrupted());
    // 返回当前线程,并归位为false interrupt标记位:ture
    System.out.println(Thread.interrupted());
    // 已经归位了
    System.out.println(Thread.interrupted());
​
    // =====================================================
    Thread t1 = new Thread(() -> {
        while(!Thread.currentThread().isInterrupted()){
            // 处理业务
        }
        System.out.println("t1结束");
    });
    t1.start();
    Thread.sleep(500);
    t1.interrupt();
}

通过打断WAITING或者TIMED_WAITING状态的线程,从而抛出异常自行处理

这种停止线程方式是最常用的一种,在框架和JUC中也是最常见的

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        while(true){
            // 获取任务
            // 拿到任务,执行任务
            // 没有任务了,让线程休眠
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("基于打断形式结束当前线程");
                return;
            }
        }
    });
    t1.start();
    Thread.sleep(500);
    t1.interrupt();
}

wait和sleep的区别?

  • 单词不一样。

  • sleep属于Thread类中的static方法、wait属于Object类的方法

  • sleep属于TIMED_WAITING,自动被唤醒、wait属于WAITING,需要手动唤醒。

  • sleep方法在持有锁时,执行,不会释放锁资源、wait在执行后,会释放锁资源。

  • sleep可以在持有锁或者不持有锁时,执行。 wait方法必须在只有锁时才可以执行。

wait方法会将持有锁的线程从owner扔到WaitSet集合中,这个操作是在修改ObjectMonitor对象,如果没有持有synchronized锁的话,是无法操作ObjectMonitor对象的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程数据汇总: 1. 线程的概念和创建方式: 线程是程序执行的基本单元,Java中可以通过继承Thread或实现Runnable接口来创建线程。 2. 线程同步的方法Java常用线程同步方法包括synchronized关键字、Lock接口、ReentrantLock、Condition接口等。 3. 线程池的概念和使用: 线程池是一种多线程处理的方式,可以通过ThreadPoolExecutor来创建线程池,提高多线程处理的效率。 4. 线程安全的集合Java中提供了多种线程安全的集合,如ConcurrentHashMap、ConcurrentLinkedQueue、CopyOnWriteArrayList等,可以在多线程环境下安全地访问集合。 5. 线程通信的方法Java线程通信的方法包括wait()、notify()、notifyAll()等,可以实现线程之间的协作和通信。 6. 线程的状态: Java线程的状态包括新建、就绪、运行、阻塞和死亡等。 7. 线程的优先级: Java线程的优先级可以通过setPriority()方法设置,优先级高的线程有更大的概率被调度执行。 8. 线程的中断: Java中可以通过interrupt()方法线程进行中断,线程可以通过isInterrupted()或interrupted()方法判断是否被中断。 9. 线程的异常处理: Java中可以通过try-catch语句对线程的异常进行处理,也可以通过UncaughtExceptionHandler接口来自定义线程的异常处理方式。 10. 线程的停止: Java中可以通过设置标志位或调用stop()方法来停止线程,但是stop()方法不建议使用,因为它可能导致线程不安全的情况发生。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值