多线程细节

1、面试题:sleep和wait的区别

相同点:

可以让线程处于冻结状态

不同点:

1、sleep必须指定时间、wait可以指定时间,也可以不指定时间。

2、sleep时间到,线程处于临时阻塞或者运行; wait如果没有指定时间,必须要通过notify或者notifyall来唤醒。

3、sleep不一定非要定义在同步中; wait必须定义在同步中

4、线程拿到锁之后,又进行sleep,线程放不放执行权?

都定义在同步中。线程执行到sleep,不会释放锁。线程执行到wait,会释放锁

synchronized(obj){
    sleep(5000);
    wait();  //放不放执行权?
}

2、线程如何停止

1、stop方法过时,有其他替代方案。

线程结束,就是run方法结束。

run方法怎么结束?

run方法中通常定义循环,只要控制住循环就可以来。

注意:万一线程在任务中处于冻结状态,那么它还能去判断标记吗?不能,怎么办

package thread;
class Demo1 implements Runnable{
    private boolean flag = true;
    public synchronized void run(){
        while (flag){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"---"+e.toString());
            }
            System.out.println(Thread.currentThread().getName()+"----->");
        }
    }

    //对标记的修改方法
    public void change(){
        flag = false;
    }
}
public class Thread_interrept {
    public static void main(String[] args) {
        Demo1 d = new Demo1();

        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();

        int x =0;
        while (true){
            if(++x == 50){
                d.change();
                break;
            }
            System.out.println("main---->"+x);
        }
        System.out.println("over");

    }
}

2、提供了一个解决方案,如果目标线程等待很长时间,则应该使用interrupt方法来中断该等待。

所谓中断线程,就是让线程从冻结状态恢复过来,让线程恢复到运行状态,重新具备cpu的运行资格。

因为是强制状态,所以会有异常发生,可以在catch中捕获异常。

在异常处理中,改变标记让循环结束,让run方法结束。

package thread;
class Demo1 implements Runnable{
    private boolean flag = true;
    public synchronized void run(){
        while (flag){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"---"+e.toString());
                change();//如果抛出异常,则表示t1激活,则改变标记状态
            }
            System.out.println(Thread.currentThread().getName()+"----->");
        }
    }

    //对标记的修改方法
    public void change(){
        flag = false;
    }
}
public class Thread_interrept {
    public static void main(String[] args) {
        Demo1 d = new Demo1();

        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();

        int x =0;
        while (true){
            if(++x == 50){
//                d.change();
                //强制对t1线程对象进行中断状态的清除
                t1.interrupt();
                t2.interrupt();
                break;
            }
            System.out.println("main---->"+x);
        }
        System.out.println("over");

    }
}

3 守护线程

也就是后台线程、一般创建的都是前台线程。

public final void setDaemon(boolean on)
//将该线程标记为守护线程,当运行的线程都是守护线程时,java虚拟机退出

 

线程前台后台运行都是一样的,获取CPU的执行权力。只有结束的时候有些不同。

前台线程通过run方法结束。

后台线程也可以通过run方法结束。

当前台线程都结束,后台线程无论处于什么状态都会自行结束。

比如:演员在前台表演,后台有忙碌的人员。前台如果结束,后台的忙碌也就没有意义了。

package thread;
class Demo1 implements Runnable{
    private boolean flag = true;
    public synchronized void run(){
        while (flag){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+"---"+e.toString());
                change();//如果抛出异常,则表示t1激活,则改变标记状态
            }
            System.out.println(Thread.currentThread().getName()+"----->");
        }
    }

    //对标记的修改方法
    public void change(){
        flag = false;
    }
}
public class Thread_interrept {
    public static void main(String[] args) {
        Demo1 d = new Demo1();

        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.setDaemon(true);  //将t2线程标记为守护线程
        t2.start();

        int x =0;
        while (true){
            if(++x == 50){
//                d.change();
                //强制对t1线程对象进行中断状态的清除
                t1.interrupt();
//t2并没有进行中断
                break;
            }
            System.out.println("main---->"+x);
        }
        System.out.println("over");

    }
}

4 优先级

高优先级线程的执行要优于低优先级。

优先级有几级?是怎么表示的?

数字越大,优先级越高。

范围:【1-10】

其中默认的初始优先级是5。最明显的三个优先级就是1、5、10。

void setPriority(int newpriprity)

或者参数可以为Tread.MAX_PRIORITY

5 线程组

表示一个线程的集合。默认的都是main组。

四个线程,若要 进行中断,则要进行四次。

如果把线程封装到一个组里面。只要对组进行interrupt就行。 

6、join和yield方法

package Thread_join;
class Demo implements Runnable{
    public void run(){
        for(int i = 0;i<20;i++){
            System.out.println(Thread.currentThread().getName()+"...."+i);
            Thread.yield(); //线程临时暂停,释放执行权,让其他线程有机会获取执行权
        }
    }
}
public class join_Demo {
    public static void main(String[] args) {
        Demo d = new Demo();
        Thread t1 = new Thread(d,"t1");
        Thread t2 = new Thread(d,"t2");
        t1.start();
        try {
            t1.join();  //t1线程在这里要加入进来执行。所以想要执行就必须有执行权。主线程把执行权释放之后,处于冻结状态。什么时候恢复?等t1线程结束之后。
            //用于临时加入一个运算的线程,让该线程运算完,程序才会继续运行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
        for(int i = 0;i<20;i++){
            System.out.println("main------>"+i);
        }
        System.out.println("over");
    }

}

7 开发中,线程的匿名内部类体现

package Thread_join;

public class in_class {
    public static void main(String[] args) {
        //用匿名内部类的方法随时创建一个线程并让其跑起来。
        new Thread() {
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "   x   " + i);
                }
            }
        //加大括号的意思是Thread子类对象
        }.start();

        Runnable r = new Runnable(){
            public void run(){
                for(int i = 0;i<20;i++){
                    System.out.println(Thread.currentThread().getName()+"   y   "+ i);
                }
            }
        };
        new Thread(r).start();

        for(int i = 0;i<20;i++){
            System.out.println(Thread.currentThread().getName()+"   z   "+ i);
        }
    }
}

面试题

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable run");
            }
        }){
            public void run(){
                System.out.println("sunrunnable run");
            }
        }.start();

到底谁会执行呢?

后面的会执行,因为子类run方法把父类的run方法覆盖了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值