JavaSE 高级开发之多线程的常用方法

多线程常用方法

1、线程命名与获取

多线程的运行状态时不确定的,所以对于多线程的操作必须有一个可以明确标识出线程对象的信息,这个信息通过名称来描述

//获取当前线程名称
//Thread.currentThread().getName()
class MyThread1 implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i < 10; i++){
            System.out.println("当前线程名称"+Thread.currentThread().getName()+" ,i = "+i);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        MyThread1 myThread = new MyThread1();
        //没有设置名称时,系统会自动分配一个名字
		new Thread(myThread).start();//没有设置名称
        new Thread(myThread).start();//没有设置名称
        new Thread(myThread,"线程1").start();//线程命名
    }
}

主方法本身就是一个线程,所有的线程都是通过主线程创建并启动的

class MyThread implements Runnable{

    @Override
    public void run() {
        System.out.println("当前线程"+Thread.currentThread().getName());
    }
}
public class Test{
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        mt.run();//通过对象名直接调用run()方法
        new Thread(mt).start();//通过线程调用
    }
}
//当前线程main
//当前线程Thread-0

2、线程休眠操作(sleep()方法)

让线程暂缓执行一段时间,等到了预计时间之后恢复执行
线程休眠会交出CPU,让CPU去执行其他的任务。但不会释放锁,也就是说如果当前线程持有某个对象的锁,即使调用sleep方法,其他线程也无法访问这个对象

//线程休眠操作
class MyThread implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
            try {
                Thread.sleep(1000);//线程休眠1000毫秒
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("当前线程"+Thread.currentThread().getName()+",i = "+i);
        }
    }
}
public class Test{
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        new Thread(mt).start();//三个线程并发执行
        new Thread(mt).start();
        new Thread(mt).start();
    }
}

3、线程让步yield()方法

暂停当前正在执行的线程对象,并执行其他线程
yield方法与sleep方法类似,让当前线程交出CPU同时不会释放锁,但是yield不能控制具体交出CPU的时间,同时yield方法只能让拥有相同优先级的线程由获取CPU执行机会

//线程让步操作
class MyThread implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            Thread.yield();//调用yield方法,使线程重新回到就绪状态
            System.out.println("当前线程"+Thread.currentThread().getName()+",i = "+i);
        }
    }
}
public class Test{
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        new Thread(mt).start();
        new Thread(mt).start();
        new Thread(mt).start();
    }
}

4、等待该线程终止join()方法

如果在主线程中调用此方法就会让主线程休眠,使得调用该方法的线程先执行完毕后在开始执行主线程

//等待该线程终止
class MyThread implements Runnable{

    @Override
    public void run() {
        try{
            System.out.println("主线程休眠前的时间");
            Test.printTime();
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName());
            System.out.println("睡眠时间结束");
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt,"线程A");
        thread.start();
        System.out.println(Thread.currentThread().getName());
        thread.join();
        System.out.println("代码结束");
    }
    public static void printTime(){
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = format.format(date);
        System.out.println(time);
    }
}

5、线程停止的三种方式

I、设置标志位使线程正常退出

//设置标志位使线程退出
class MyThread implements Runnable {
    private boolean flag = true;//定义标记位

    @Override
    public void run() {
        int i = 1;
        while (flag) {
            try {
                Thread.sleep(100);
                System.out.println("第" + i + "次执行,线程名为:" + Thread.currentThread().getName());
                i++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void setFlag(boolean flag){
        this.flag = flag;
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt,"线程A");
        thread.start();
        Thread.sleep(200);
        mt.setFlag(false);
        System.out.println("代码结束");
    }
}

II、使用stop方法强制退出(不安全)

//使用stop方法强制退出
public static void main(String[] args) throws InterruptedException {
	MyThread mt = new MyThread();
	Thread thread = new Thread(mt,"线程A");
	thread.start();
	Thread.sleep(200);
	thread.stop();//直接使用stop()方法强制退出
	System.out.println("代码结束");
}

III、使用Thread类中的interrupt()方法中断线程

//使用Thread.interrupt()方法使线程退出
class MyThread implements Runnable {
    private boolean flag = true;

    @Override
    public void run() {
        int i = 1;
        while (flag) {
            try {
                /**
                 * 线程在这里阻塞之后,会调用interrupt()方法
                 * 清除中断标志,抛出异常
                 */
                Thread.sleep(100);
                boolean bool = Thread.currentThread().isInterrupted();
                if(bool){
                    System.out.println("非阻塞状态下执行此操作,线程状态"+bool);
                    break;
                }
                System.out.println("第"+i+"次执行,线程名为:"+Thread.currentThread().getName());
                i++;
            } catch (InterruptedException e) {
                System.out.println("退出");
                /**
                 * 这里退出阻塞状态,中断标志被系统自动清除
                 * flag被重新设置为false
                 */
                boolean bool = Thread.currentThread().isInterrupted();
                System.out.println(bool);
                return;
            }
        }
    }
    public void setFlag(boolean flag){
        this.flag = flag;
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt,"线程A");
        thread.start();
        Thread.sleep(200);
        thread.interrupt();
        System.out.println("代码结束");
    }
}

6、线程优先级的设置与取得

线程优先级越高越有可能先执行,但只是可能

设置优先级:public final void setPriority(int newPriority)
取得优先级:public final int getPriority()

设置优先级的几个等级

  1. 最高优先级:public final static int MAX_PRIORITY = 10;
  2. 中等优先级:public final static int NORM_PRIORITY = 5;
  3. 最低优先级:public final static int MIN_PRIORITY = 1;
//设置优先级
class MyThread implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            System.out.println("当前线程名称"+Thread.currentThread().getName()+" ,i = "+i);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        Thread thread1 = new Thread(mt,"线程1");
        Thread thread2 = new Thread(mt,"线程2");
        Thread thread3 = new Thread(mt,"线程3");
        thread1.setPriority(Thread.MIN_PRIORITY);//设置优先级
        thread2.setPriority(Thread.MAX_PRIORITY);
        thread3.setPriority(Thread.MIN_PRIORITY);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
//取得主线程的优先级
public class Test {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getPriority());
        //主线程的优先级为中等优先级:5
    }
}

7、守护线程

Java中有两种线程:守护线程和用户线程
守护线程是一种特殊的线程,它属于是一种陪伴线程,只要当前JVM进程中存在任何一个非守护线程没有结束,守护线程就在工作;只有当最后一个非守护线程结束时,守护线程才会随着JVM一同停止工作。

可以通过isDaemon()方法来区别它们:如果返回false,则说明该线程是“用户线程”;否则就是“守护线程”。典型的守护线程就是垃圾回收线程。

//观察守护线程
class MyThread implements Runnable {
    private int i;
    @Override
    public void run() {
        try {
            while (true) {
                i++;
                System.out.println("线程名称:" + Thread.currentThread().getName() + ",i=" + i +
                        ",是否为守护线程:"
                        + Thread.currentThread().isDaemon());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("线程名称:" + Thread.currentThread().getName() + "中断线程了");
        }
    }
}
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new MyThread(),"子线程A");
        // 设置线程A为守护线程,此语句必须在start方法之前执行
        thread1.setDaemon(true);
        thread1.start();
        Thread thread2 = new Thread(new MyThread(),"子线程B");
        thread2.start();
        Thread.sleep(3000);
        // 中断非守护线程
        thread2.interrupt();
        Thread.sleep(10000);
        System.out.println("代码结束");
    }
}

猜你喜欢

转载自blog.csdn.net/ly52014/article/details/88597408