1.java中多线程中同步是什么?
在多线程程序下,同步能控制对共享资源的访问。如果没有同步,当一个线程在修改这个变量时,另一个线程在使用或更新同一个变量,这样容易导致程序出现错误结果。
2.实现多线程的几种方法?
Java线程可以通过实现Runnable接口或是继承Thread类来实现,若是打算多继承,则提前使用继承Runnable接口。
3.Thread.start()与Thread.run()有何区别?
使用Thread.start()启动线程,是线程处于就绪状态,当cpu分配时间给该线程时,由JVM调度run()方法执行。
4.为什么需要start()方法和run()方法?可以直接用run()方法来完成任务吗?
我们需要start()&run()方法是因为JVM创建一个单独的线程不同于普通的方法的调用,所以这项工作由线程的start方法来完成,start方法由本地方法实现,需要显式地调用,使用这两个方法的另一个好处就是任何一个对象都能作为线程运行,只要它实现了Runnable接口,这就避免了因继承了Thread类而造成的java多继承的问题。
5.什么是ThreadLocal类?怎么使用它?
ThreadLocal是一个线程级别的局部变量,并非“本地线程”。ThreadLocal为每个使用该变量的线程提供了一个独立的变量副本,每个线程修改副本时不影响其它线程对象的副本(译者注)。
下面是线程局部变量(ThreadLocal variables)的关键点:
一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。
ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程。
当多个线程访问ThreadLocal实例时,每个线程维护ThreadLocal提供的独立的变量副本。
6.什么时候抛出InvalidMonitorException异常,为什么?
调用wait()/notify()/notifyAll()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出IllegalMonitorStateException的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用wait()/notify()/notifyAll()时)。
7.Sleep()、suspend()和wait()之间有什么区别?
Thread.sleep()使当前线程在指定的时间处于“非运行”状态。线程一直持有对象的监视器。比如一个线程当前在一个同步块或同步方法中,其它线程不能进入该块或方法中。如果另一线程调用了interrupt()方法,它将唤醒那个“睡眠的”线程。
注意:sleep()是一个静态方法。这意味着只对当前线程有效,一个常见的错误就是调用t.sleep(),(这里的t是一个不同于当前线程的线程)。即便是执行t.sleep(),也是当前线程进入睡眠,而不是t线程。t.suspend()是过时的方法,使用suspend()导致线程进入停滞状态,该线程会一直持有对象的监视器,suspend()容易引起死锁的问题。
Object.wait()使当前线程处于“不可运行”状态,和sleep()不同的是wait是Object的方法而不是thread。调用object.wait()时,线程先要获得这个对象的对象锁,当前线程必须在锁对象保持同步,把当前线程添加到等待队列中,随后另一线程可以同步同一个对象锁来调用Object.notify(),这样将唤醒原来等待中的线程,然后释放该锁。基本上wait()/notify()与sleep()/interrupt()类似,只是前者需要回去对象锁。
8.在静态方法上使用同步时会发生什么事?
同步静态方法时会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。
9.当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗?
可以,一个非同步方法总是可以被调用而不会有任何问题。
10.在一个对象上两个线程可以调用两个不同的同步实例方法吗?
不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完该方法释放对象锁后才能执行其它同步方法。
11.什么是死锁?
死锁就是两个或两个以上的线程被无限制地阻塞,线程之间相互等待所需的资源。这种情况可能发生在彼此都需要得到对方占有的锁,但彼此都不释放这个锁。