Excise_Thread2

1.下列关于多线程中锁机制正确的是( )。
A.关键字synchronized只能用于方法声明上。
B.成员方法使用synchronized,那么当前方法的锁对象为当前方法所属的对象
C.静态方法使用synchronized,那么当前方法的锁对象为当前方法所属对象
D.为了尽量避免多线程带来的安全问题,尽可能的扩大synchronized修饰的代码范围。
解析:正确B。A选项synchronized既可以用在方法声明上也可以用在方法体中。C选项静态方法中使用同步块(synchronized(同步监视器对象){}),锁对象是当前类对象(Class实例);D选项,锁的范围扩大会降低程序执行效率。在保证程序的线程安全情况下,尽量保证同步范围缩小,使用同步代码块
2.下列选项中关于synchronized的使用正确的是:(C)。
A.private synchronized Object o;
B.void go() {
synchronized() { /* code here / }
}
C.public synchronized void go() { /
code here / }
D.private synchronized (this) void go() { /
code here */ }
解析:正确C。A选项synchronized只能锁方法(同步方法)或锁代码块(同步块),局部变量不能使用修饰词。B选项没有写出同步监视器对象,编译报错。D选项方法声明上只能使用synchronized形式修饰,锁普通方法默认锁this,锁静态方法默认锁类对象。
3.哪个关键字可以对对象加锁?( )
A.transient B.synchronized C.serialize D.static
解析:B正确。A选项,使用transient控制成员变量不被序列化,当反序列化时也是得到null值,基本数据类型反序列化也是null
4.下列代码说法正确的是:( )。
public class DaemonThread extends Thread{
public DaemonThread(String name){
super(name);//只是设置线程名,将Thread_0设置名为dtThread
}
public void run() {
while (true) {
System.out.println(“Daemon thread running…”);
}
}
public static void main(String[] args) {
DaemonThread dt = new DaemonThread(“dtThread”);
dt.setDaemon(true);
dt.start();
} }
A.名为dtThread的线程为守护线程
B.运行上述代码,main 线程一退出,则虚拟机退出
C.运行上述代码,程序会一直跑下去,因为main线程结束了,但dt线程是一个无限循环,还没有结束,虚拟机不能退出
D.main线程是守护线程
解析:AB正确,main是一个前台线程,不是守护线程

简答题
1.简述线程池的工作原理
线程池:(可以创建多个线程)
线程池是一个管理线程的机制,主要解决两个问题:

  • 1.控制线程数量
  • 2.重用线程(任务过多,只用固定数量的线程去解决问题)

工作原理:
当创建线程池时,传入的参数为最大线程数量,底层源码会判断传入的最大线程数量是否大于核心线程数量,如果大于(不可能大于),会先创建核心线程数量(核心数量和最大线程数量相等)。
创建线程是在ThreadPoolExecutor构造方法参数的默认工厂参数创建,
通过execute(任务)传入任务时,无论任务数量是否大于线程池数量,如果小于线程池数量,会分配线程执行任务。若任务大于线程池数量,
超过的任务会被放在阻塞队列排队等待线程空下来。
线程关闭,shutdown()会将阻塞队列的线程任务执行完再关闭,shutdownNow()会立即关闭,清空阻塞队列的线程任务,关闭线程池。

2.什么是守护线程?它与普通线程有什么区别?
守护线程:

  • 守护线程也称为后台线程(非守护线程又叫前台线程)
  • 是通过普通线程调用setDaemon(boolean on)方法设置而来的,因此在创建上与普通线程一样,
  • 区别:守护线程的结束时机与普通线程不同,即:进程的结束(守护线程才结束)。
  • 进程结束:当一个进程中的所有普通线程都结束时,进程就会结束,此时会杀掉所有正在运行的守护线程。
  • 什么时候设置守护线程:通常当我们不关心某个线程的任务什么时候停下来时,他可以一直运行,但是程序主要的工作都结束时它应当跟着结束,这样的任务就适合放在守护线程上执行比如GC就是在守护线程上运行的。

3.synchronized关键字的用法
synchronized 锁方法和锁代码块的联系?
①synchronized 即可以修饰普通方法,也可以修饰静态方法。使用synchronized修饰的方法称为“同步方法”;

  • 即:多个线程不能同时在方法内部执行,只能有先后顺序的一个一个执行。
  • 将并发操作同一临界资源的过程改为同步执行就可以有效解决并发安全问题。
  • 在静态方法上使用synchronized后,该方法一定是同步方法,由于静态方法属于类,所以一定具有同步效果

②也可以在方法体中使用同步块,可以更准确的控制需要排队执行的代码片段。语法如下:

synchronized(同步监视器对象){
 		//需要多线程同步执行的代码片段
 }

需要注意的是:
①在普通方法中使用同步块,同步监视器可以为任意类型对象,在普通方法中要保证多个线程同步监视器相同,否则同步无效,可以将同步监视器声明为成员变量或指定为this(当前正在调用的对象),视情况而定。

②在静态方法中使用同步块,同步监视器对象为当前类的类对象(Class实例)

4.什么是单例模式?
单利设计模式(Singleton pattern)是java中最简单的设计模式之一,属于创建型模式,它提供了一种创建对象的最佳方式。
单利设计模式要保证一个类仅有一个实例,并提供一个全局都可以访问的方式(因为不能在外界new对象,所以获取该类的实例的方法必须设置为static的,同时实例也是静态的,因为静态方法中只能使用静态资源)
好处是:为了节省内存,节省时间
开发步骤:

  • 1.私有化构造方法不让外界随意new对象
  • 2.自己在类的内部创建一个对象
  • 3.提供一个公共的访问方式,并返回自己创建的对象
    实现方式有:饿汉式和懒汉式

5.懒汉式和饿汉式有什么区别?如何实现?
区别:①饿汉式对象加载时间过长,占用内存,但为线程安全。懒汉式为线程不安全,但可以通过线程同步机制将懒汉式设置成线程安全的。节约内存
饿汉式:在创建单例模式的类时就直接创建该类对象,在调用方法获取对象时直接返回对象
懒汉式 :又叫按需加载/延时加载,在创建单例模式的类中只声明对象的引用,在调用方法时获取对象时先判断该对象是否为null,为null则创建对象返回

编程题

  1. 采用匿名内部类的方式创建2个线程,一个线程为计时线程,每隔2s输出当前时间的毫秒表示,
    另一个线程为前台线程,任务是线程开始,休眠10秒结束,当前台线程结束,计时线程也随之结束。请完成以上案例。
package JAVA_API.num14_Thread.homework;

/**
 * 1. 采用匿名内部类的方式创建2个线程,一个线程为计时线程,每隔2s输出当前时间的毫秒表示,
 * 另一个线程为前台线程,任务是线程开始,休眠10秒结束,当前台线程结束,计时线程也随之结束。请完成以上案例。
 * @author yyc
 * 2021/9/23 19:12
 */
public class Time {
    public static void main(String[] args) {
        //计时线程
        Thread time = new Thread(){
            @Override
            public void run(){
                while(true) {//并不知道什么时候结束
                    //每隔2s输出当前时间的毫秒表示
                    System.out.println(System.currentTimeMillis());
                    try {
                        //每隔两秒
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        //前台线程
        Thread thread2 = new Thread(){
            @Override
            public void run(){
                //线程开始,休眠10秒结束
                System.out.println("开始休眠...");
                try {
                   Thread.sleep(10000);
                 } catch (InterruptedException e) {
                e.printStackTrace();
                }
                System.out.println("休眠结束!");
            }
        };
        thread2.start();
        time.setDaemon(true);
        time.start();
    }
}

  1. 创建2个线程对象表示2个人,二人都要完成在客厅看电视5s,然后去卫生间5s的任务,已知二人同时开始执行任务。
    要求:2个人可以同时在客厅看电视,但是上厕所不能同时上,只能排队上
package JAVA_API.num14_Thread.homework;

/**
 * 2. 创建2个线程对象表示2个人,二人都要完成在客厅看电视5s,然后去卫生间5s的任务,已知二人同时开始执行任务。
 * 	要求:2个人可以同时在客厅看电视,但是上厕所不能同时上,只能排队上
 * @author yyc
 * 2021/9/23 19:29
 */
public class Person {
	//用来控制锁对象,保证线程锁是同一个。
    static Object obj = new Object();
    public static void main(String[] args) {
        Thread person1 = new Thread(){
            @Override
            public void run(){
                //二人都要完成在客厅看电视
                System.out.println(getName() + ",person1看电视...");
                //看5s电视
                try {
                    Thread.sleep(5000);
                //当前对象上锁,
                synchronized(obj) {
                    //去卫生间5s
                    System.out.println(getName() + ",person1上厕所,锁门");
                    Thread.sleep(5000);
                }
                    System.out.println(getName() + ",person1上完厕所,开门!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread person2 = new Thread(){
            @Override
            public void run(){
                //二人都要完成在客厅看电视
                System.out.println(getName() + ",person2看电视...");
                //看5s电视
                try {
                    Thread.sleep(5000);
                    //当前对象上锁,
                    synchronized(obj) {
                        //去卫生间5s
                        System.out.println(getName() + ",person2上厕所,锁门");
                        Thread.sleep(5000);
                    }
                    System.out.println(getName() + ",person2上完厕所,开门!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        person1.start();
        person2.start();
    }
}

封装成方法

      Person person1 = new Person();
        Thread t1 = new Thread(){
          @Override
          public void run(){
              person1.live();
          }
        };
        Thread t2 = new Thread(){
            @Override
            public void run(){
                person1.live();
            }
        };
        t1.start();
        t2.start();
    }
    public  void live(){
        Thread t = new Thread();
        System.out.println(t.getName() + "看电视...");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (this){
            System.out.println(t.getName() + "上厕所");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(t.getName() + "上完厕所");
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值