java学习笔记第十三天

多线程之间的通信问题
package lesson13;


class Resource{
    String name;
    String sex;
}

class Input implements Runnable{

    Resource r;
    Input(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        int x = 0;
        while(true){
            if(x==0){
                r.name = "mike";
                r.sex = "male";
            }
            else{
                r.name = "J";
                r.sex = "female";
            }
            x = (x+1)%2;
        }
    }
}

class Output implements Runnable{

    Resource r ;
    Output(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            System.out.println(r.name+"--"+r.sex);
        }
    }
}


public class test1 {
    public static void main(String args[]){
        Resource r = new Resource();
        Input i = new Input(r);
        Output o = new Output(r);
        Thread t1 = new Thread(i);
        Thread t2 = new Thread(o);
        t1.start();
        t2.start();

    }
}

<<<
J--female
mike--male
J--male
J--male
J--female
J--female
mike--female
mike--male
J--male
J--female
mike--female
mike--female
mike--male
mike--male
mike--female
J--male

为什么J的性别变成了male?
因为当Input获得执行权时,此时已经修改了name为J,然后立刻失去了执行权,此时Output获得了执行权,然后就打印了J–male.

要怎样解决这个问题?

package lesson13;


class Resource{
    String name;
    String sex;
}

class Input implements Runnable{

    Resource r;
    Input(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        int x = 0;
        while(true){
            synchronized (r) {
                if (x == 0) {
                    r.name = "mike";
                    r.sex = "male";
                } else {
                    r.name = "J";
                    r.sex = "female";
                }
            }
            x = (x+1)%2;
        }
    }
}

class Output implements Runnable{

    Resource r ;
    Output(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            synchronized (r){
                System.out.println(r.name+"--"+r.sex);
            }
        }
    }
}


public class test1 {
    public static void main(String args[]){
        Resource r = new Resource();
        Input i = new Input(r);
        Output o = new Output(r);
        Thread t1 = new Thread(i);
        Thread t2 = new Thread(o);
        t1.start();
        t2.start();

    }
}

<<<
mike--male
mike--male
mike--male
mike--male
mike--male
mike--male
J--female
J--female
J--female

此时正常了

等待唤醒机制

涉及的方法

  1. wait() :让线程处于冻结状态,被wait的线程会被存储到线程池中。
  2. notify(): 唤醒线程池中的一个线程(任意)。
  3. notifyAll():唤醒线程池中的所有线程。
    这些方法都必须定义在同步中。
    因为浙西方法适用于操作线程状态的方法。
    必须要明确操作的是哪个线程

为什么操作线程的方法wait(),notify(),notifyAll()定义在Object中?

因为这些方法是监视器的方法,监视器其实就是锁。
可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
package lesson13;


class Resource{
    String name;
    String sex;
    boolean flag = false;
}

class Input implements Runnable{

    Resource r;
    Input(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        int x = 0;
        while(true){
            synchronized (r) {
                if(r.flag){
                    try {
                        r.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (x == 0) {
                    r.name = "mike";
                    r.sex = "male";
                } else {
                    r.name = "J";
                    r.sex = "female";
                }
                r.flag = true;
                r.notify();
            }
            x = (x+1)%2;

        }
    }
}

class Output implements Runnable{

    Resource r ;
    Output(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            synchronized (r){//官方文档称r为监视器(锁)
                if(!r.flag){
                    try {
                        r.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(r.name+"--"+r.sex);
                r.flag = false;
                r.notify();
            }
        }
    }
}


public class test1 {
    public static void main(String args[]){
        Resource r = new Resource();
        Input i = new Input(r);
        Output o = new Output(r);
        Thread t1 = new Thread(i);
        Thread t2 = new Thread(o);
        t1.start();
        t2.start();

    }
}

<<<
J--female
mike--male
J--female
mike--male
J--female
mike--male
J--female
mike--male

r.wait()表示将该线程放入r的线程池中。
此处的flag是标识读函数是否读取信息。

package lesson13;


class Resource{
    private String name;
    private String sex;
    private boolean flag = false;
    //此时属性变成了私有属性,我们需要提供对外的方法来修改这些属性
//    但是需要注意的是,我们需要对这个方法进行同步操作,以防修改了姓名没有修改性别
//    输出函数亦是如此
    public synchronized void set(String name,String sex){
        if (flag){
            try {
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        this.name = name;
        this.sex = sex;
        flag = true;
        notify();
    }

    public synchronized void get()  {
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(name+"---"+sex);
        flag = false;
        notify();
    }
}

class Input implements Runnable{

    Resource r;
    Input(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        int x = 0;
        while(true){
            if (x == 0) {
                    r.set("mike","male");
                } else {
                    r.set("J","female");
                }
            x = (x+1)%2;
        }
    }
}

class Output implements Runnable{

    Resource r ;
    Output(Resource r){
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            r.get();
        }
    }
}


public class test1 {
    public static void main(String args[]){
        Resource r = new Resource();
        Input i = new Input(r);
        Output o = new Output(r);
        Thread t1 = new Thread(i);
        Thread t2 = new Thread(o);
        t1.start();
        t2.start();
    }
}

<<<
J---female
mike---male
J---female
mike---male
J---female
mike---male
J---female
mike---male

如果有多个生产者消费者,或有什么情况发生?

package lesson13;

class newResource{
    private String name;
    private int count = 1;
    private boolean flag = false;
    public synchronized void set(String name){
        if (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.name = name+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
        flag = true;
        notify();
    }

    public synchronized void get(){
        if (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"---消费者-----"+this.name);
        flag = false;
        notify();
    }
}

class Producer implements Runnable{

    private newResource r = new newResource();

    Producer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.set("duck");
        }
    }
}

class Consumer implements Runnable{

    private newResource r = new newResource();

    Consumer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.get();
        }
    }
}

public class test2 {
    public static void main(String args[]){
        newResource r = new newResource();
        Producer p = new Producer(r);
        Consumer c = new Consumer(r);
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
        Thread t3 = new Thread(p);
        Thread t4 = new Thread(c);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

会出现某个鸭子没有被消费,或者是某个鸭子被消费多次

因为如果t1生产完一只鸭子后,t2在等待被唤醒状态,因为随机唤醒一个线程,此时t2有生产一只鸭子,这是再唤醒t3,t3消费掉第二只,子则不会消费掉第一只鸭子。

那么如何避免这种情况呢?

这种情况出现的原因在于,判断flag后,直接进入睡眠状态,等被唤醒时,不再判断flag是否满足生产条件,就直接生产。

因此将if改为while,则生产线程被唤醒时,可以对其再次进行flag判断

package lesson13;

class newResource{
    private String name;
    private int count = 1;
    private boolean flag = false;
    public synchronized void set(String name){
        while (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.name = name+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
        flag = true;
        notify();
    }

    public synchronized void get(){
        while (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"---消费者-----"+this.name);
        flag = false;
        notify();
    }
}

class Producer implements Runnable{

    private newResource r = new newResource();

    Producer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.set("duck");
        }
    }
}

class Consumer implements Runnable{

    private newResource r = new newResource();

    Consumer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.get();
        }
    }
}

public class test2 {
    public static void main(String args[]){
        newResource r = new newResource();
        Producer p = new Producer(r);
        Consumer c = new Consumer(r);
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
        Thread t3 = new Thread(p);
        Thread t4 = new Thread(c);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
<<<
Thread-0---生产者---duck1
Thread-3---消费者-----duck1
Thread-0---生产者---duck2
Thread-1---消费者-----duck2
Thread-0---生产者---duck3
Thread-3---消费者-----duck3

但是此时又有可能引发死锁
t0生产完鸭子后,唤醒t1,t1不满足生产条件,唤醒t0,两个重复唤醒。死锁了

如何解决以上的问题?
没有特定的方法使t1来唤醒t2或者t3

于是我们使用notifyall()来会来唤醒所有的线程

package lesson13;

class newResource{
    private String name;
    private int count = 1;
    private boolean flag = false;
    public synchronized void set(String name){
        while (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.name = name+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
        flag = true;
        notifyAll();
    }

    public synchronized void get(){
        while (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"---消费者-----"+this.name);
        flag = false;
        notifyAll();
    }
}

class Producer implements Runnable{

    private newResource r = new newResource();

    Producer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.set("duck");
        }
    }
}

class Consumer implements Runnable{

    private newResource r = new newResource();

    Consumer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.get();
        }
    }
}

public class test2 {
    public static void main(String args[]){
        newResource r = new newResource();
        Producer p = new Producer(r);
        Consumer c = new Consumer(r);
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
        Thread t3 = new Thread(p);
        Thread t4 = new Thread(c);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

此时就不会出现问题了。但是降低了效率,因为所有的线程都被唤醒了
java 对于上述情况已经有了新的改进,将锁抽象为接口,并提供获取锁与释放锁的方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Condition将原来Object中的方法封装成了一个对象,之前synchronized同步代码块中只能有一组锁的操作(wait,notify)(同步只有一个锁),现在,一个lock锁对象可以挂载多个condition对象。

一个Condition实例本质上绑定到一个锁。 要获得特定Condition实例的Condition实例,请使用其newCondition()方法。

package lesson13;
import java.util.concurrent.locks.*;

class newResource{
    private String name;
    private int count = 1;
    private boolean flag = false;
//创建一个锁对象
    Lock lock = new ReentrantLock();
//    通过已有的锁获取该锁上的监视器对象
    Condition con = lock.newCondition();

    public  void set(String name){
        lock.lock();
        try{
            while (flag){
                try {
                    con.await();//注意此处
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            this.name = name+count;
            count++;
            System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
            flag = true;
            con.signalAll();
        }finally {
            lock.unlock();//将锁释放
        }

    }

    public synchronized void get(){
        lock.lock();
        try{
            while (!flag){
                try {
                    con.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"---消费者-----"+this.name);
            flag = false;
            con.signalAll();
        }finally {
            lock.unlock();
        }

    }
}

class Producer implements Runnable{

    private newResource r = new newResource();

    Producer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.set("duck");
        }
    }
}

class Consumer implements Runnable{

    private newResource r = new newResource();

    Consumer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.get();
        }
    }
}

public class test2 {
    public static void main(String args[]){
        newResource r = new newResource();
        Producer p = new Producer(r);
        Consumer c = new Consumer(r);
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
        Thread t3 = new Thread(p);
        Thread t4 = new Thread(c);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

目前一个锁监视了生产者与消费者。我们希望生产者能唤醒消费者,消费者能唤醒生产者。

package lesson13;
import java.util.concurrent.locks.*;

class newResource{
    private String name;
    private int count = 1;
    private boolean flag = false;
//    通过已有的锁获取该锁上的监视器对象
    Condition pro_con = lock.newCondition();
    // 生产者锁
    Condition con_con = lock.newCondition();
    // 消费者锁
    public  void set(String name){
        lock.lock();
        try{
            while (flag){
                try {
                    pro_con.await();//注意此处
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            this.name = name+count;
            count++;
            System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
            flag = true;
            con_con.signal();//唤醒消费者
        }finally {
            lock.unlock();
        }

    }

    public synchronized void get(){
        lock.lock();
        try{
            while (!flag){
                try {
                    con_con.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"---消费者-----"+this.name);
            flag = false;
            pro_con.signalAll();
        }finally {
            lock.unlock();
        }

    }
}

class Producer implements Runnable{

    private newResource r = new newResource();

    Producer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.set("duck");
        }
    }
}

class Consumer implements Runnable{

    private newResource r = new newResource();

    Consumer(newResource r){
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            r.get();
        }
    }
}

public class test2 {
    public static void main(String args[]){
        newResource r = new newResource();
        Producer p = new Producer(r);
        Consumer c = new Consumer(r);
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
        Thread t3 = new Thread(p);
        Thread t4 = new Thread(c);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

Lock接口:

替代了同步代码块,将同步的隐式操作转化为显示操作。
同时更为灵活,可以一个锁上加上多组监视器。
lock(): 获取锁
unlock():释放锁

Condition接口:

出现替代了Object中的wait,notify,notifyall方法。
将这些监视器方法单独进行了封装,变成了condition监视器对象。
await();
signgal();
signalAll();

wait 和sleep的区别?

1. wait 可以指定时间也可以不指定时间,sleep必须要指定时间
2. 在同步中时,对cpu的执行权和锁的处理不同
	wait:释放执行权,释放锁。
	sleep: 不释放执行权,不释放锁。
3. 

在这里插入图片描述
当 t0,t1,t2都进入show的同步代码块时,都进行wait状态,而t4进入method时,唤醒了所有的线程,此时所有线程都具备了执行资格,但是为获取锁,因为t4并未释放锁。此时t0,t1,t2谁获取锁就执行谁。

停止线程
  1. stop方法。(已废弃)
  2. run 方法结束

怎么控制线程的任务结束?
在任务中都会有循环结构,只要控制住循环就可以结束循环。

package lesson13;

class stopThread implements Runnable{

    private boolean flag = true;
    @Override
    public synchronized void run() {
        while (flag){
            System.out.println(Thread.currentThread().getName()+"-------");
        }
        System.out.println("over");
        }

    public void setFlag() {
        this.flag = false;
    }
}


public class test3 {
    public static void main(String[] args) {
        stopThread s = new stopThread();
        Thread t1 = new Thread(s);
        Thread t2 = new Thread(s);
        t1.start();
        t2.start();
        for (int i = 0;;i++){
            if (i==50){
                s.setFlag();
                break;
            }
            System.out.println(Thread.currentThread().getName()+""+i);
        }
    }
}

但是以上情况有停不下的时候

package lesson13;

class stopThread implements Runnable{

    private boolean flag = true;
    @Override
    public synchronized void run() {
        while (flag){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-------");
        }

        }

    public void setFlag() {
        this.flag = false;
    }
}


public class test3 {
    public static void main(String[] args) {
        stopThread s = new stopThread();
        Thread t1 = new Thread(s);
        Thread t2 = new Thread(s);
        t1.start();
        t2.start();
        for (int i = 0;;i++){
            if (i==50){
                s.setFlag();
                break;
            }
            System.out.println(Thread.currentThread().getName()+""+i);
        }
        System.out.println("over");
    }
}

此时主线程停了,而t0 和t1

为什么没用呢?

如果线程处于冻结状态就无法读取标记。

但是如何解决中这种情况呢?
Thread中的interrupt方法
在这里插入图片描述
可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备cpu执行资格。

强制动作会抛出InterruptedException,需要处理

package lesson13;

class stopThread implements Runnable{

    private boolean flag = true;
    @Override
    public synchronized void run() {
        while (flag){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"-------"+e);
            }
            System.out.println(Thread.currentThread().getName()+"-------");
            flag=false;
        }
        }

    public void setFlag() {
        this.flag = false;
    }
}


public class test3 {
    public static void main(String[] args) {
        stopThread s = new stopThread();
        Thread t1 = new Thread(s);
        Thread t2 = new Thread(s);
        t1.start();
        t2.start();
        for (int i = 0;;i++){
            if (i==50){
//                s.setFlag();
                t1.interrupt();
                t2.interrupt();
                break;
            }
            System.out.println(Thread.currentThread().getName()+""+i);
        }
        System.out.println("over");
    }
}
<<<
main45
main46
main47
main48
main49
over
Thread-0-------java.lang.InterruptedException
Thread-0-------
Thread-1-------java.lang.InterruptedException
Thread-1-------

线程中其他常见的方法?
在这里插入图片描述

package lesson13;

class stopThread implements Runnable{

    private boolean flag = true;
    @Override
    public synchronized void run() {
        while (flag){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"-------"+e);
            }
            System.out.println(Thread.currentThread().getName()+"-------");
            flag=false;
        }
        }

    public void setFlag() {
        this.flag = false;
    }
}


public class test3 {
    public static void main(String[] args) {
        stopThread s = new stopThread();
        Thread t1 = new Thread(s);
        Thread t2 = new Thread(s);
        t1.start();
        t2.setDaemon(true);
        t2.start();
        for (int i = 0;;i++){
            if (i==50){
                t1.interrupt();//此时没有进行t2的强制中断操作。
                break;
            }
            System.out.println(Thread.currentThread().getName()+""+i);
        }
        System.out.println("over");
    }
}
<<<
main45
main46
main47
main48
main49
over
Thread-0-------java.lang.InterruptedException
Thread-0-------

也能正常结束

setDaemon将线程转化为守护进程,当前台线程都结束时,无论后台进程处于什么状态都会消失。

join方法

package lesson13;

class Demo implements Runnable{

    @Override
    public void run() {
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread().getName()+"----"+x);
        }
    }
}

public class test4 {
    public static void main(String args[]) throws InterruptedException {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t1.join();
        t2.start();
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread().getName()+"----"+x);
        }

    }
}

<<<
Thread-0----0
Thread-0----1
Thread-0----2
Thread-0----3
Thread-0----4
Thread-0----5
Thread-0----6
Thread-0----7
Thread-0----8
Thread-0----9
main----0
main----1
main----2
main----3
Thread-1----0
main----4
Thread-1----1
main----5
Thread-1----2
main----6
Thread-1----3
main----7
Thread-1----4
main----8
Thread-1----5
main----9
Thread-1----6
Thread-1----7
Thread-1----8
Thread-1----9
package lesson13;

class Demo implements Runnable{

    @Override
    public void run() {
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread().getName()+"----"+x);
        }
    }
}

public class test4 {
    public static void main(String args[]) throws InterruptedException {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();
        t1.join();
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread().getName()+"----"+x);
        }

    }
}
<<<
Thread-0----0
Thread-1----0
Thread-0----1
Thread-1----1
Thread-0----2
Thread-1----2
Thread-0----3
Thread-1----3
Thread-0----4
Thread-1----4
Thread-0----5
Thread-1----5
Thread-0----6
Thread-1----6
Thread-0----7
Thread-1----7
Thread-0----8
Thread-1----8
Thread-0----9
Thread-1----9
main----0
main----1
main----2
main----3
main----4
main----5
main----6
main----7
main----8
main----9

Process finished with exit code 0

此时join值影响main线程等待t1执行结束后,再执行,不影响t2的执行。

package lesson13;

class Demo implements Runnable{

    @Override
    public void run() {
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread().getName()+"----"+x);
        }
    }
}

public class test4 {
    public static void main(String args[]) throws InterruptedException {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();
        t1.join();
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread()+"----"+x);
        }

    }
}
<<<
Thread-1----0
Thread-0----0
Thread-1----1
Thread-0----1
Thread-1----2
Thread-1----3
Thread-1----4
Thread-0----2
Thread-1----5
Thread-0----3
Thread-1----6
Thread-0----4
Thread-0----5
Thread-1----7
Thread-0----6
Thread-1----8
Thread-0----7
Thread-1----9
Thread-0----8
Thread-0----9
Thread[main,5,main]----0
Thread[main,5,main]----1
Thread[main,5,main]----2
Thread[main,5,main]----3
Thread[main,5,main]----4
Thread[main,5,main]----5
Thread[main,5,main]----6
Thread[main,5,main]----7
Thread[main,5,main]----8
Thread[main,5,main]----9

Thread[main,5,main]----9 这里的5是优先级

serPriority()可以设置线程的优先级。

package lesson13;

class Demo implements Runnable{

    @Override
    public void run() {
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread()+"----"+x);
        }
    }
}

public class test4 {
    public static void main(String args[]) throws InterruptedException {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.setPriority(Thread.MAX_PRIORITY);
        t2.start();
        for(int x = 0;x<10;x++){
            System.out.println(Thread.currentThread()+"----"+x);
        }

    }
}
<<<
Thread[main,5,main]----0
Thread[main,5,main]----1
Thread[main,5,main]----2
Thread[main,5,main]----3
Thread[main,5,main]----4
Thread[main,5,main]----5
Thread[main,5,main]----6
Thread[main,5,main]----7
Thread[main,5,main]----8
Thread[main,5,main]----9
Thread[Thread-0,5,main]----0
Thread[Thread-0,5,main]----1
Thread[Thread-0,5,main]----2
Thread[Thread-1,10,main]----0
Thread[Thread-1,10,main]----1
Thread[Thread-1,10,main]----2
Thread[Thread-1,10,main]----3
Thread[Thread-1,10,main]----4
Thread[Thread-1,10,main]----5
Thread[Thread-1,10,main]----6
Thread[Thread-1,10,main]----7
Thread[Thread-1,10,main]----8
Thread[Thread-1,10,main]----9
Thread[Thread-0,5,main]----3
Thread[Thread-0,5,main]----4
Thread[Thread-0,5,main]----5
Thread[Thread-0,5,main]----6
Thread[Thread-0,5,main]----7
Thread[Thread-0,5,main]----8
Thread[Thread-0,5,main]----9

默认情况下,线程优先级为5,最高为10,优先级最高并不是只运行该线程,而是调用该线程的可能性大于其他线程。

在这里插入图片描述
面试题

class Demo implements Runnable{
    @Override
    public void run(Thread t) {
        
    }
}

以上代码有错吗?如果有错编译时错误出现在哪一行?

第一行因为该类没有实现接口中定义的run方法(不能传参,传参相当于重载),

package lesson13;

public class test5 {
    public static void main(String args[]){
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable run");
            }
        })
        {
            public void run(){
                System.out.println("subThread run");
            }
        }.start();
    }
}
<<<
subThread run
package lesson13;

public class test5 {
    public static void main(String args[]){
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable run");
            }
        })
        {
        }.start();
    }
}
<<<
runnable run
package lesson13;

public class test5 {
    public static void main(String args[]){
        new Thread()
        {
        }.start();
    }
}
<<<


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值