0.Java 中多线程同步是什么?
在多线程程序下,同步能控制对共享资源的访问。如果没有同步,当一个 Java 线程在修改一个共享变量时,另外一个线程正在使用或者更新同一个变量,这样容易导致程序出现错误的结果。
1.解释实现多线程的几种方法?
一 Java 线程可以实现 Runnable 接口或者继承 Thread 类来实现,当你打算多重继承时,优先选择实现 Runnable。
2.Thread.start ()与 Thread.run ()有什么区别?
Thread.start ()方法(native)启动线程,使之进入就绪状态,当 cpu 分配时间该线程时,由 JVM 调度执行 run ()方法。
3.为什么需要 run ()和 start ()方法,我们可以只用 run ()方法来完成任务吗?
我们需要 run ()&start ()这两个方法是因为 JVM 创建一个单独的线程不同于普通方法的调用,所以这项工作由线程的 start 方法来完成,start 由本地方法实现,需要显示地被调用,使用这俩个方法的另外一个好处是任何一个对象都可以作为线程运行,只要实现了 Runnable 接口,这就避免因继承了 Thread 类而造成的 Java 的多继承问题。
4.什么是 ThreadLocal 类,怎么使用它?
ThreadLocal 是一个线程级别的局部变量,并非“本地线程”。ThreadLocal 为每个使用该变量的线程提供了一个独立的变量副本,每个线程修改副本时不影响其它线程对象的副本(译者注)。
下面是线程局部变量(ThreadLocal variables)的关键点:
一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。
ThreadLocal 实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程。
当多个线程访问 ThreadLocal 实例时,每个线程维护 ThreadLocal 提供的独立的变量副本。
常用的使用可在 DAO 模式中见到,当 DAO 类作为一个单例类时,数据库链接(connection)被每一个线程独立的维护,互不影响。(基于线程的单例)
7.在静态方法上使用同步时会发生什么事?
同步静态方法时会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。
8.当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗?
可以,一个非同步方法总是可以被调用而不会有任何问题。实际上,Java 没有为非同步方法做任何检查,锁对象仅仅在同步方法或者同步代码块中检查。如果一个方法没有声明为同步,即使你在使用共享数据 Java 照样会调用,而不会做检查是否安全,所以在这种情况下要特别小心。一个方法是否声明为同步取决于临界区访问(critial section access),如果方法不访问临界区(共享资源或者数据结构)就没必要声明为同步的。
下面有一个示例说明:Common 类有两个方法 synchronizedMethod1()和 method1(),MyThread 类在独立的线程中调用这两个方法。
- public class Common {
- public synchronized void synchronizedMethod1() {
- System.out.println (“synchronizedMethod1 called”);
- try {
- Thread.sleep (1000);
- } catch (InterruptedException e) {
- e.printStackTrace ();
- }
- System.out.println (“synchronizedMethod1 done”);
- }
- public void method1() {
- System.out.println (“Method 1 called”);
- try {
- Thread.sleep (1000);
- } catch (InterruptedException e) {
- e.printStackTrace ();
- }
- System.out.println (“Method 1 done”);
- }
- }
- public class MyThread extends Thread {
- private int id = 0;
- private Common common;
- public MyThread (String name, int no, Common object) {
- super(name);
- common = object;
- id = no;
- }
- public void run () {
- System.out.println (“Running Thread” + this.getName ());
- try {
- if (id == 0) {
- common.synchronizedMethod1();
- } else {
- common.method1();
- }
- } catch (Exception e) {
- e.printStackTrace ();
- }
- }
- public static void main (String[] args) {
- Common c = new Common ();
- MyThread t1 = new MyThread (“MyThread-1″, 0, c);
- MyThread t2 = new MyThread (“MyThread-2″, 1, c);
- t1.start ();
- t2.start ();
- }
- }
这里是程序的输出:
- Running ThreadMyThread-1
- synchronizedMethod1 called
- Running ThreadMyThread-2
- Method 1 called
- synchronizedMethod1 done
- Method 1 done
结果表明即使 synchronizedMethod1()方法执行了,method1()也会被调用。
9.在一个对象上两个线程可以调用两个不同的同步实例方法吗?
不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完该方法释放对象锁后才能执行其它同步方法。看下面代码示例非常清晰:Common 类有 synchronizedMethod1()和 synchronizedMethod2()方法,MyThread 调用这两个方法。
- public class Common {
- public synchronized void synchronizedMethod1() {
- System.out.println (“synchronizedMethod1 called”);
- try {
- Thread.sleep (1000);
- } catch (InterruptedException e) {
- e.printStackTrace ();
- }
- System.out.println (“synchronizedMethod1 done”);
- }
- public synchronized void synchronizedMethod2() {
- System.out.println (“synchronizedMethod2 called”);
- try {
- Thread.sleep (1000);
- } catch (InterruptedException e) {
- e.printStackTrace ();
- }
- System.out.println (“synchronizedMethod2 done”);
- }
- }
- public class MyThread extends Thread {
- private int id = 0;
- private Common common;
- public MyThread (String name, int no, Common object) {
- super(name);
- common = object;
- id = no;
- }
- public void run () {
- System.out.println (“Running Thread” + this.getName ());
- try {
- if (id == 0) {
- common.synchronizedMethod1();
- } else {
- common.synchronizedMethod2();
- }
- } catch (Exception e) {
- e.printStackTrace ();
- }
- }
- public static void main (String[] args) {
- Common c = new Common ();
- MyThread t1 = new MyThread (“MyThread-1″, 0, c);
- MyThread t2 = new MyThread (“MyThread-2″, 1, c);
- t1.start ();
- t2.start ();
- }
- }
10.什么是死锁
死锁就是两个或两个以上的线程被无限的阻塞,线程之间相互等待所需资源。这种情况可能发生在当两个线程尝试获取其它资源的锁,而每个线程又陷入无限等待其它资源锁的释放,除非一个用户进程被终止。就 JavaAPI 而言,线程死锁可能发生在一下情况。
当两个线程相互调用 Thread.join ()
当两个线程使用嵌套的同步块,一个线程占用了另外一个线程必需的锁,互相等待时被阻塞就有可能出现死锁。
11.什么是线程饿死,什么是活锁?
线程饿死和活锁虽然不想是死锁一样的常见问题,但是对于并发编程的设计者来说就像一次邂逅一样。
当所有线程阻塞,或者由于需要的资源无效而不能处理,不存在非阻塞线程使资源可用。JavaAPI 中线程活锁可能发生在以下情形:
当所有线程在程序中执行 Object.wait (0),参数为 0 的 wait 方法。程序将发生活锁直到在相应的对象上有线程调用 Object.notify ()或者 Object.notifyAll ()。 当所有线程卡在无限循环中。
相关连接:
http://blog.csdn.net/dongwujing/article/details/7647858
http://blog.csdn.net/walkingmanc/article/details/7004826
http://www.blogjava.net/hankchen/archive/2009/12/29/307680.html
相关推荐
多线程面试题
面试题和答案. 有多线程, 数据库,框架题目等知识点
这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些问题网上有、可能有些问题对应的答案也有、也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会...
java经典多线程面试题。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
2022java面试题、JVM面试题、多线程面试题、并发编程、Redis面试题、MySQL面试题、Java2022面试题、Netty面试题、Elasticsearch面试题、Tomcat面试题、Dubbo面试题、Kafka面试题、Linux面试题、2021面试题、java面试...
java多线程面试经典,内含50道常被面试官问到的java多线程题。
史上最全 Java 多线程面试题及答案.docx
15个顶级Java多线程面试题答案
Java多线程面试题,作为多线程面试题,非常经典。
Java多线程运行机制、并发处理面试题目深层解读。
Java 多线程面试题及答案
Java 多线程面试题.one
高级Java多线程面试题及回答
java面试题之多线程.pdf
java大厂的多线程面试题,涵盖了基础和进阶的多线程的理论和实际的应用,供各位下载使用。多线程面试题
多线程&并发面试题 JVM面试题 Mysql面试题 Redis面试题 Memcached面试题 MongoDB面试题 Spring面试题 Spring Boot面试题 Spring Cloud面试题 RabbitMQ面试题 Dubbo 面试题 MyBatis 面试题 ZooKeeper 面试题 数据结构...
【Java核心知识面试】-15个顶级Java多线程面试题答案