多线程(二)

17) 为什么wait()和notify()方法要在同步块中调用?
Java API强制要求这样做,否则会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。


18) 为什么你应该在循环中检查等待条件?
防止处于等待状态的线程收到错误的唤醒消息。如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。
因此,当一个等待线程醒来时,不能认为它原来的等待状态仍然是有效的,
在notify()方法调用之后和等待线程醒来之前这段时间它可能会改变。这就是在循环中使用wait()方法效果更好的原因


19) Java中的同步集合与并发集合有什么区别?
同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发集合的可扩展性更高。在Java1.5之前程序员们只有同步集合来用且在多线程并发的时候会导致争用,阻碍了系统的扩展性。


20) Java中堆和栈有什么不同?
因为栈是一块和线程紧密相关的内存区域。每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。
而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,
这时volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值。


21) 什么是线程池? 为什么要使用它?
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。
为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。
从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;


22) 如何写代码来解决生产者消费者问题?
在现实中你解决的许多线程问题都属于生产者消费者模型,就是一个线程生产任务供其它线程进行消费,
比较低级的办法是用wait和notify来解决这个问题,比较赞的办法是用Semaphore 或者 BlockingQueue来实现生产者消费者模型,


23) 如何避免死锁?
死锁是由于进程互相争夺资源导致系统无法继续向前运行的一种僵尸状态,如果没有外力作用下,系统很难继续向前运行。
死锁的4个必要条件:


请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
避免死锁最简单的方法:
预防为主:对共享资源的访问做好保护,做好检查
检查死锁:一般情况下是死锁发生之后才会发现的
解除死锁:查找死锁的原因,找出最终的解决办法。


24) Java中活锁和死锁有什么区别?
活锁:进程的状态不断改变,但是却不能继续执行。
死锁:进程的状态不能改变也不能继续执行。


25) 怎么检测一个线程是否拥有锁?
java.lang.Thread中有一个方法叫holdsLock(object),如果当且仅当当前线程拥有某个具体对象的锁,返回true。
java.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁。
Object o = new Object();
@Test
public void test1() throws Exception {
    new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized(o) {
                System.out.println("thread2: holdLock: " + 
                    Thread.holdsLock(o));
            }
        }
    }).start();
    System.out.println("thread1: holdLock: " + Thread.holdsLock(o));
    Thread.sleep(2000);
}
thread1: holdLock: false
thread2: holdLock: true


26) 你如何在Java中获取线程堆栈?
对于不同的操作系统,有多种方法来获得Java进程的线程堆栈。
当你获取线程堆栈时,JVM会把所有线程的状态存到日志文件或者输出到控制台。
在Windows你可以使用Ctrl + Break组合键来获取线程堆栈,Linux下用kill -3命令。
你也可以用jstack这个工具来获取,它对线程id进行操作,你可以用jps这个工具找到id。

27) JVM中哪个参数是用来控制线程的栈堆栈小的
-Xss参数用来控制线程的堆栈大小,-Xss1024K表示设置栈的大小为1M


28) Java中synchronized 和 ReentrantLock 有什么不同?
Java在过去很长一段时间只能通过synchronized关键字来实现互斥,它有一些缺点。比如你不能扩展锁之外的方法或者块边界,
尝试获取锁时不能中途取消等。Java 5 通过Lock接口提供了更复杂的控制来解决这些问题。 ReentrantLock 类实现了 Lock,它拥有与 synchronized 相同的并发性和内存语义且它还具有可扩展性。
(1)、相同点:Lock()能完成synchronized所实现的所有功能.
(2)、不同点:Lock()使用起来更灵活方便。
Synchronized同步的代码块或方法,jvm会自动释放。
Lock()的释放unlock()必须在finally()方法中手动释放,防止运行过程中异常抛出线程挂掉。


29) Thread类中的yield()方法有什么作用?
yield()方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。
它是一个静态方法而且只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在进入到暂停状态后马上又被执行。

30) Java中ConcurrentHashMap的并发度是什么?
并发度是ConcurrentHashMap类构造函数的一个可选参数,默认值为16,这样在多线程情况下就能避免争用。


31) Java中Semaphore是什么?
Java中的Semaphore是一种新的同步类,它是一个计数信号。从概念上讲,从概念上讲,信号量维护了一个许可集合。
如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release()添加一个许可,从而可能释放一个正在阻塞的获取者。
但是,不使用实际的许可对象,Semaphore只对可用许可的号码进行计数,并采取相应的行动。信号量常常用于多线程的代码中,比如数据库连接池


32)如果你提交任务时,线程池队列已满。会时发会生什么?
如果一个任务不能被调度执行那么ThreadPoolExecutor’s submit()方法将会抛出一个RejectedExecutionException异常。


33) Java线程池中submit() 和 execute()方法有什么区别?
两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 
而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,
其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。更多详细信息请点击这里。


34) 什么是阻塞式方法?
阻塞式方法是指程序会一直等待该方法完成期间不做其他事情,ServerSocket的accept()方法就是一直等待客户端连接。
这里的阻塞是指调用结果返回之前,当前线程会被挂起,直到得到结果之后才会返回。
此外,还有异步和非阻塞式方法在任务完成前就返回。更多详细信息请点击这里。


35) Swing是线程安全的吗? 为什么?
Swing不是线程安全的。当我们说swing不是线程安全的常常提到它的组件,这些组件不能在多线程中进行修改,
所有对GUI组件的更新都要在AWT线程中完成,而Swing提供了同步和异步两种回调方法来进行更新。


36) Java中invokeAndWait 和 invokeLater有什么区别?
这两个方法是Swing API 提供给Java开发者用来从当前线程而不是事件派发线程更新GUI组件用的。
InvokeAndWait()同步更新GUI组件,比如一个进度条,一旦进度更新了,进度条也要做出相应改变。
如果进度被多个线程跟踪,那么就调用invokeAndWait()方法请求事件派发线程对组件进行相应更新。而invokeLater()方法是异步调用更新组件的。更多详细信息请点击这里。


37) Swing API中那些方法是线程安全的?
这个问题又提到了swing和线程安全,虽然组件不是线程安全的但是有一些方法是可以被多线程安全调用的,
比如repaint(), revalidate()。 JTextComponent的setText()方法和JTextArea的insert() 和 append() 方法也是线程安全的。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值