zoukankan      html  css  js  c++  java
  • Java多线程常用面试题(含答案,精心总结整理)

    现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?

    目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。

    核心:

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。 
    比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。 
    想要更深入了解,建议看一下join的源码,也很简单的,使用wait方法实现的。
    
    t.join(); //调用join方法,等待线程t执行完毕 
    t.join(1000); //等待 t 线程,等待时间是1000毫秒。
    public static void main(String[] args) {
            method01();
            method02();
        }
     
        /**
         * 第一种实现方式,顺序写死在线程代码的内部了,有时候不方便
         */
        private static void method01() {
            Thread t1 = new Thread(new Runnable() {
                @Override public void run() {
                    System.out.println("t1 is finished");
                }
            });
            Thread t2 = new Thread(new Runnable() {
                @Override public void run() {
                    try {
                        t1.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t2 is finished");
                }
            });
            Thread t3 = new Thread(new Runnable() {
                @Override public void run() {
                    try {
                        t2.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t3 is finished");
                }
            });
     
            t3.start();
            t2.start();
            t1.start();
        }
     
     
        /**
         * 第二种实现方式,线程执行顺序可以在方法中调换
         */
        private static void method02(){
            Runnable runnable = new Runnable() {
                @Override public void run() {
                    System.out.println(Thread.currentThread().getName() + "执行完成");
                }
            };
            Thread t1 = new Thread(runnable, "t1");
            Thread t2 = new Thread(runnable, "t2");
            Thread t3 = new Thread(runnable, "t3");
            try {
                t1.start();
                t1.join();
                t2.start();
                t2.join();
                t3.start();
                t3.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它?

    Lock读写锁机制可以实现! 

    在Java中Lock接口比synchronized块的优势是什么?

     Lock接口最大的优势是为读和写分别提供了锁。

    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Random;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    
    
    
    public class JoinTest2 {    
      
        public static void main(String[] args) {  
            final TheData theData = new TheData();
            for(int i=0;i<4;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        theData.get();
                    }
                }).start();
            }
            for(int i=0;i<4;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        theData.put(new Random().nextInt(1000));
                    }
                }).start();
            }        
        }  
        
    
    } 
    
    class  TheData{
        private Integer data = 0;
        private ReadWriteLock rwLock = new ReentrantReadWriteLock();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        public void get(){
            rwLock.readLock().lock();//读锁开启,读进程均可进入
            try{//用try finally来防止因异常而造成的死锁
                System.out.println(Thread.currentThread().getName()+"read lock is ready.."+sdf.format(new Date()));
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName()+"read data is"+data);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                rwLock.readLock().unlock();//读锁解锁
            }
        }
        
        public void put(Integer data){
            rwLock.writeLock().lock();//写锁开启,这时只有一个写线程进入
            try{//用try finally来防止因异常而造成的死锁
                System.out.println(Thread.currentThread().getName()+"write lock is ready.."+sdf.format(new Date()));
                Thread.sleep(1000);
                this.data = data;
                System.out.println(Thread.currentThread().getName()+"write data is"+data);                
    
            }catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                rwLock.writeLock().unlock();//写锁解锁
            }
        }
    }

    在java中wait和sleep方法的不同?

    通常会在电话面试中经常被问到的Java线程面试问题。 
    最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。

    此处我想理一下Java多线程的基础知识: 
    - Java的多线程锁是挂在对象上的,并不是在方法上的。即每个对象都有一个锁,当遇到类似synchronized的同步需要时,就会监视(monitor)每个想使用本对象的线程按照一定的规则来访问,规则也就是在同一时间内只能有一个线程能访问此对象。 
    - Java中获取锁的单位是线程。当线程A获取了对象B的锁,也就是对象B的持有标记上写的是线程A的唯一标识,在需要同步的情况下的话,只有线程A能访问对象B。 
    - Thread常用方法有:start/stop/yield/sleep/interrupt/join等,他们是线程级别的方法,所以并不会太关心锁的具体逻辑。 
    - Object的线程有关方法是:wait/wait(事件参数)/notify/notifyAll,他们是对象的方法,所以使用的时候就有点憋屈了,必须当前线程获取了本对象的锁才能使用,否则会报异常。但他们能更细粒度的控制锁,可以释放锁。

  • 相关阅读:
    sizeof和strlen区别
    Reverse Words in a String
    删除字符串中重复的字符
    Reverse String
    数组中一个数字出现的次数超过了数组长度的一半,请找出这个数
    输出数组中大于等于左边所有数且小于等于右边所有数的元素
    java获取数据库里表的名字
    [转]C++编写Config类读取配置文件
    c# App.Config详解
    pitch yaw roll是什么
  • 原文地址:https://www.cnblogs.com/zhaoyan001/p/9894115.html
Copyright © 2011-2022 走看看