【Java】多线程

空扰寡人 提交于 2020-02-01 20:59:28

继承Thread类实现多线程

class MyThread extends Thread{
    private String title;
    public MyThread(String title){
        this.title = title;
    }

    @Override
    public void run(){
        for (int i = 0;i < 10;i++){
            System.out.println(title + ",i = " + i);
        }
    }
}
public class Hello {
    public static void main(String[] args) throws Exception{
        MyThread my1 = new MyThread("thread1");
        MyThread my2 = new MyThread("thread2");
        my1.start();
        my2.start();
    }
}

多线程的启动必须通过调用start方法。

实现Runnable接口实现多线程

class MyThread2 implements Runnable{
    private String title;
    public MyThread2(String title){
        this.title = title;
    }

    @Override
    public void run(){
        for (int i = 0;i < 10;i++){
            System.out.println(title + ",i = " + i);
        }
    }
}

public class Hello {
    public static void main(String[] args) throws Exception{
        MyThread2 my3 = new MyThread2("thread3");
        MyThread2 my4 = new MyThread2("thread4");
        new Thread(my3).start();
        new Thread(my4).start();
    }
}

Runnable接口没有了继承的局限性,但是该接口并没有start函数,所以无法直接调用,就需要利用Thread提供的构造方法来调用。

public Thread(Runnable target);

同时这里可以使用内部类和lambda表达式。

Thread与Runnable区别

实际上Thread也是实现了Runnable的接口,并覆盖了run方法。这内部牵扯到代理模式。

线程状态转换图

多线程常用的操作方法

线程名命和获取

public Thread(Runnable terget,String name);//使用构造方法命名

public final synchronized void setName(String name);//使用一般方法命名

public final String getName();//获取线程名字

在Thread类里有个currentThread()函数可以夺取当前线程对象。

public static native Thread currentThread();
class MyThread2 implements Runnable{
    @Override
    public void run(){
        for (int i = 0;i < 10;i++){
            System.out.println(Thread.currentThread().getName()+",i="+i);
        }
    }
}

public class Hello {
    public static void main(String[] args) throws Exception{
        MyThread2 my = new MyThread2();
        new Thread(my).start();
        new Thread(my).start();
        new Thread(my,"hh").start();
    }
}

sleep方法

class MyThread implements Runnable{
    @Override 
    public void run(){
        for(int i=0;i<1000;i++){
            try {
                Thread.sleep(1000);
            }catch(InterruptedException e){
                e.printstackTrace();
            }
        }
    }
}

该方法会让线程进入休眠。等时间过后才恢复执行。

线程休眠会交出CPU,让CPU执行其他任务。但sleep后不会释放锁。

yield方法

class MyThread implements Runnable {
    @Override
    public void run() {
        for(int i = 0;i < 3;i++){
            Thread.yield();
            System.out.println(Thread.currentThread().getName());
        }
    }
}

该方法会让线程让步,会暂停当前在执行的线程,并执行其他线程。

与sleep方法类似,同样不会释放锁。

yield不能控制交出CPU的时间。并且yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

yield不会让线程阻塞,而是让线程回到Runnable状态(就绪状态)

join方法

class MyThread implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("开始");
            Thread.sleep(3000);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

public class Hello {
    public static void main(String[] args) throws Exception{
        MyThread my = new MyThread();
        Thread thread = new Thread(my,"子线程");
        thread.start();
        thread.join();
        System.out.println("结束");
    }
}

等待该线程终止。

在主线程中调用后,会先让祖贤成进入休眠,直到调用join的线程run方法执行完毕,才会继续执行主线程。

线程停止

1:使用一个标记位,通过判断让线程运行完停止。

2:调用stop方法退出。(该方法不安全,一般不用)
为什么不安全:stop方法会在任意时刻完全停止,并解除该线程获得的锁。所以可能会导致线程同步的混乱问题。

3:使用Thread类中的一个interrupt()中断线程


线程优先级

优先级越高的线程越有可能执行。

public final void setPriority(int new Priority);//Thread类下的设置优先级

public final int getPriority();//获取优先级

Thread类提供了几个常量:

  1. 最高优先级:public final static int MAX_PRIORITY=10;
  2. 中等优先级:public final static int NORM_PRIORITY=5;
  3. 最低优先级:public final static int MIN_PRIORITY=1;

主方法只是一个中等优先级。

线程是有继承关系的,比如当A线程中启动B线程,那么B和A的优先级将是一样的。

守护线程

守护线程是一种特殊的线程,它属于是一种陪伴线程。

简单点说java中有两种线程:用户线程和守护线程。可以通过isDaemon()方法来区别它们:如果返回false,则说明该线程是“用户线程”;否则就是“守护线程”。

典型的守护线程就是垃圾回收线程。只要当前VM进程中存在任何一个非守护线程没有结束,守护线程就在工作;只有当最后一个非守护线程结束时,守护线程才会随着JVM一同停止工作。

使用setDaemon(bool isDaemon);来设置当前线程是否为守护线程。

该方法必须在start之前执行

线程的同步和死锁






易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!