千家信息网

Java多线程面试题实例分析

发表于:2024-10-31 作者:千家信息网编辑
千家信息网最后更新 2024年10月31日,这篇文章主要介绍了Java多线程面试题实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java多线程面试题实例分析文章都会有所收获,下面我们一起来看看吧。问题一A线
千家信息网最后更新 2024年10月31日Java多线程面试题实例分析

这篇文章主要介绍了Java多线程面试题实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java多线程面试题实例分析文章都会有所收获,下面我们一起来看看吧。

问题一

A线程正在执行一个对象中的同步方法,B线程是否可以同时执行同一个对象中的非同步方法?

可以,两个线程运行所需资源不同,不需要抢占。

案例一、

package duoxiancheng2;/** * @author yeqv * @program A2 * @Classname Ms1 * @Date 2022/2/7 19:08 * @Email w16638771062@163.com */public class Ms1 {    //A线程正在执行一个对象中的同步方法,B线程是否可以同时执行同一个对象中的非同步方法?    Object a = new Object();    public static void main(String[] args) {        var t = new Ms1();        new Thread(() -> t.a1()).start();//A线程        new Thread(() -> t.a2()).start();//B线程    }    void a1() {        synchronized (a) {            System.out.println("同步方法");        }    }    void a2() {        System.out.println("非同步方法");    }}

运行结果:

问题二

同上,B线程是否可以同时执行同一个对象中的另一个同步方法?

不可以,两个线程执行需要一个共同资源,共同资源加了同步锁,同一时刻只能一个线程占用。

案例二、

package duoxiancheng2;import java.util.concurrent.TimeUnit;/** * @author yeqv * @program A2 * @Classname Ms2 * @Date 2022/2/7 19:25 * @Email w16638771062@163.com */public class Ms2 {    //同上,B线程是否可以同时执行同一个对象中的另一个同步方法?    Object a = new Object();    public static void main(String[] args) {        var t = new Ms2();        new Thread(() -> t.a1()).start();//A线程        new Thread(() -> t.a2()).start();//B线程    }    void a1() {        synchronized (a) {            System.out.println("进入同步方法1");            try {                TimeUnit.SECONDS.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("同步方法1结束");        }    }    void a2() {        synchronized (a) {            System.out.println("进入同步方法2");            try {                TimeUnit.SECONDS.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("同步方法2结束");        }    }}

运行结果:

线程A先运行,占用资源。

等线程A运行完释放资源后,线程B才可以进入执行

线程B执行完

问题三

线程抛出异常会释放锁吗?

会,线程出现异常抛出后立刻释放资源。

案例三、

package duoxiancheng2;import java.util.concurrent.TimeUnit;/** * @author yeqv * @program A2 * @Classname Ms3 * @Date 2022/2/7 19:41 * @Email w16638771062@163.com */public class Ms3 {    //线程抛出异常会释放锁吗?    Object a = new Object();    public static void main(String[] args) {        var t = new Ms3();        new Thread(() -> t.a1()).start();//A线程        new Thread(() -> t.a2()).start();//B线程    }    void a1() {        int c = 3;        int b;        synchronized (a) {            System.out.println("进入同步方法1");            try {                b = c / 0;                System.out.println(b);                TimeUnit.SECONDS.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("同步方法1结束");        }    }    void a2() {        synchronized (a) {            System.out.println("进入同步方法2");            try {                TimeUnit.SECONDS.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("同步方法2结束");        }    }}

结果: 方法一出现异常,立刻释放资源。线程二开始执行

问题四

写一个程序,证明AtomicInteger类比synchronized更高效

synchronized更高效

案例一

package duoxiancheng2;import java.util.concurrent.atomic.AtomicInteger;/** * @author yeqv * @program A2 * @Classname Ms4 * @Date 2022/2/7 20:04 * @Email w16638771062@163.com */public class Ms4 {    AtomicInteger n = new AtomicInteger(10000);    int num = 10000;    public static void main(String[] args) {        var t = new Ms4();        new Thread(t::minus, "T1").start();        new Thread(t::minus, "T2").start();        new Thread(t::minus, "T3").start();        new Thread(t::minus, "T4").start();        new Thread(t::minus, "T5").start();        new Thread(t::minus, "T6").start();        new Thread(t::minus, "T7").start();        new Thread(t::minus, "T8").start();    }    void minus() {        var a = System.currentTimeMillis();        while (true) {           /* if (n.get() > 0) {                n.decrementAndGet();                System.out.printf("%s 售出一张票,剩余%d张票。 %n", Thread.currentThread().getName(), n.get());            } else {                break;            }*/            synchronized (this) {                if (num > 0) {                    num--;                    System.out.printf("%s 售出一张票,剩余%d张票。 %n", Thread.currentThread().getName(), num);                } else {                    break;                }            }        }        var b = System.currentTimeMillis();        System.out.println(b - a);    }}

synchronized结果:

AtomicInteger结果:

问题五

写一个程序证明AtomXXX类的多个方法并不构成原子性

package demo16;import java.util.ArrayList;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;/** * 写一个程序证明AtomXXX类的多个方法并不构成原子性 */public class T {    AtomicInteger count = new AtomicInteger(0);    void m() {        for (int i = 0; i < 10000; i++) {            if (count.get() < 100 && count.get() >= 0) { //如果未加锁,之间还会有其他线程插进来                count.incrementAndGet();            }        }    }    public static void main(String[] args) {        T t = new T();        List threads = new ArrayList<>();        for (int i = 0; i < 10; i++) {            threads.add(new Thread(t::m, "thread" + i));        }        threads.forEach(Thread::start);        threads.forEach((o) -> {            try {                //join()方法阻塞调用此方法的线程,直到线程t完成,此线程再继续。通常用于在main()主线程内,等待其它线程完成再结束main()主线程。                o.join(); //相当于在main线程中同步o线程,o执行完了,main线程才有执行的机会            } catch (InterruptedException e) {                e.printStackTrace();            }        });        System.out.println(t.count);    }}

问题六

写一个程序,在main线程中启动100个线程,100个线程完成后,主线程打印"完成"

package cn.thread;import java.util.concurrent.CountDownLatch;/** * 写一个程序,在main线程中启动100个线程,100个线程完成后,主线程打印"完成" * * @author webrx [webrx@126.com] * @version 1.0 * @since 16 */public class T12 {    public static void main(String[] args) {        CountDownLatch latch = new CountDownLatch(100);        for (int i = 0; i < 100; i++) {            new Thread(() -> {                String tn = Thread.currentThread().getName();                System.out.printf("%s : 开始执行...%n", tn);                System.out.printf("%s : 执行完成,程序结束。%n", tn);                latch.countDown();            }, "T" + i).start();        }        try {            latch.await();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("---------------------------------------");        System.out.println("100个线程执行完了。");        String tn = Thread.currentThread().getName();        System.out.printf("%s : 执行完成,程序结束。%n", tn);    }}

关于"Java多线程面试题实例分析"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"Java多线程面试题实例分析"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

0