首页 > 试题广场 >

以下JAVA程序的输出是什么()

[单选题]
以下JAVA程序的输出是什么()
public class HelloSogou{
     public static synchronized void main(String[] a){
         Thread t=new Thread(){
             public void run(){Sogou();}
     };
     t.run();
     System.out.print("Hello");
     }
     static synchronized void Sogou(){
     System.out.print("Sogou");
    }
}
  • HelloSogou
  • SogouHello
  • Hello
  • 结果不确定
推荐
答案:B
这里调用 t.run();
并没有启动一个新的线程,启动一个新线程要用t.start();
所以执行顺序是先执行run(),再执行 System.out.print("HELLO");

编辑于 2015-01-26 15:16:48 回复(14)
我觉得误区有两个:一个是run和start区别,Thread.run()是调用方法,Thread. start()是启动线程;另一个是锁持有问题。这个题是调用方法,和多线程就无关。本题只有一个线程,持有HelloSogou.class锁。那么,就是另一个问题:同步方法调用另一个同步方法的锁问题?

public synchronized void methodA(int a, int b){}
public synchronized void methodB(int a){
     methodA(a, 0);
}
首先要明白两个问题,1.锁的对象是谁?2.谁持有了锁?
假设方法A和B是在同一个类Test中的两个方法。
Test t=new Test();
t.methodB();
调用methodB()方法,获得锁,锁是对象t;锁谁持有?当前线程(不可以说是methodB持有该锁),methodB又调用methodA,也需要锁t,该线程已持有t,当然可以直接调用methodA。

类比到此题,只有一个主线程,调用main,持有HelloSogou.class锁,那当然可以直接调用Sogou方法。

第二,如果是t.statrt(),那么这个题,静态同步函数的锁是该类的字节码文件.class。此题中,main函数和Sogou方法都是static的,所以持有相同 HelloSogou.class ,那么,在main线程(main 是一个线程也是一个进程 )中又开了一个线程,调用Sogou方法,锁会冲突。

我的分析是:调用main函数(一个线程),main函数开启另一个线程,并启动,但是main函数和Sogou方法是同一个锁,所以main函数执行完毕后才会释放锁,Sogou方法才会执行,这就是为什么,换成start,是HelloSogou。
第三,将Sogou方法的锁改为其他.class锁,那么,HelloSogou和SogouHello都可能出现。因为没有互斥现象了,变为抢占式的了。
编辑于 2016-10-09 16:53:18 回复(42)

第一点是run与start方法区别,调用run时只是单纯执行方法,故按代码顺序执行下来结果就是SogouHello。

接着我们再来看看把run换成start,结果是HelloSogou,这是为什么呢。

首先调用start是开始了一个线程,那么现在程序中有了两个线程主线程main和线程T。

这就涉及本题第二个知识点了,函数使用的锁是this(即对象本身),若函数被static修饰则锁为 类名.class.

那么题目中两个函数都是使用了同一个锁即HelloSogou.class,当执行t.start时,t线程准备调用Sogou方法,但是锁对象已被主线程占用,故要等待主线程执行完System.out.print("Hello")后释放锁才可以执行自己的Sogou方法。故此结果是HelloSogou

发表于 2017-06-23 12:51:38 回复(22)
以下是我的理解:
Synchronize在这里有两个地方使用到:
1.修饰main方法(静态)
2.修饰静态的sougou方法
当synchronize关键字修饰静态方法的时候,对方法所属的类加锁,即HelloSougou.Class

代码执行过程如下:
首先执行main()方法,main方法获得锁---》t.run()不会创建线程,只是当作普通方法执行,因此Sougou()是在主线程里执行,输出Sogou ---》System.out.println("Hello") --》结束。
其实自始至终都只有主线程的存在,所以没有存在过锁竞争,代码按照顺序执行

但是如果这里是t.start(),执行过程如下:
执行main方法,main方法获得锁--》t.start()创建线程(thread1)--》t.start自动执行run方法,锁此时在主线程,线程阻塞--》主线程执行System.out.println("Hello"),执行完毕,释放锁---->thread1获取锁,执行Sougou方法,输出Sougou--》结束  此时输出为HelloSougou
发表于 2020-02-17 23:30:22 回复(2)
1. 要使用t.start()才启动这个线程。
2. 题目中的synchronized关键字修饰了static方法,产生对Class对象的加锁,但是Java的内置锁是可重入的,所以不会死锁。
编辑于 2015-09-04 23:26:43 回复(2)
B.
run()方法中是线程代码,但是该线程对象并没有启动线程(thread.start()),所以这里的run()方法只是一个普通的方法,顺序执行。如果加入了t.start()方法,那么多线程就会启动,输出的结果将不确定。
发表于 2015-08-14 17:06:58 回复(5)
选择B
虽然主方法有synchronized关键字修饰,但是对结果没有什么影响。程序先创建一个线程t,然后调用了线程的run方法,这里只是普通的调用了run方法,所以会等run方法输出Sogou后继续执行,然后输出Hello,结果为B
发表于 2015-01-12 12:00:13 回复(0)
B : t.run()实质是普通的方法调用而已。
发表于 2015-01-23 12:49:33 回复(0)

直接调用run()方法,相当于调用了一个普通的Java方法,当前线程并没有任何改变,也不会启动新线程。上述代码实际上是在main()方法内部又调用了run()方法,打印sogou语句是在main线程中执行的,没有任何新线程被创建。

必须调用Thread实例的start()方法才能启动新线程,如果我们查看Thread类的源代码,会看到start()方法内部调用了一个private native void start0()方法,native修饰符表示这个方法是由JVM虚拟机内部的C代码实现的,不是由Java代码实现的。

发表于 2021-02-03 14:52:07 回复(0)
关键在于这里的
public static synchronized void main(String[] a)     和 static synchronized void Sogou()
修饰在静态方法上,那么锁住的是这个类。

如果使用run(),那么就是在同一个线程中执行的,此时的两个方都在主线程中,在运行的时候都持有这个类的锁,不需要任何等待,
所以就是按照正常的顺序执行即可,这时候的结果是SogouHello。

但是,如果使用了start(),那么就是开启了另外的线程,需要main方法执行完毕退出,才轮得到run()里面的语句执行。
这时候的结果是HelloSogou。
发表于 2018-11-20 19:24:22 回复(0)

第一点是run与start方法区别,调用run时只是单纯执行方法,故按代码顺序执行下来结果就是SogouHello。

接着我们再来看看把run换成start,结果是HelloSogou,这是为什么呢。

首先调用start是开始了一个线程,那么现在程序中有了两个线程主线程main和线程T。

这就涉及本题第二个知识点了,函数使用的锁是this(即对象本身),若函数被static修饰则锁为 类名.class.

那么题目中两个函数都是使用了同一个锁即HelloSogou.class,当执行t.start时,t线程准备调用Sogou方法,但是锁对象已被主线程占用,故要等待主线程执行完System.out.print("Hello")后释放锁才可以执行自己的Sogou方法。故此结果是HelloSogou

发表于 2018-07-15 16:32:26 回复(0)
考察并发编程相关知识点。第一点,同一个线程内,比如这里的 main线程内的代码是串行执行的;第二,开启一个线程必须用 start() 方法,直接调用 run() 方法与正常的对象调用方法机制无任何差异。
发表于 2016-12-05 15:48:57 回复(0)
B,在不使用Start方法的时候,该线程没有被创建,仅仅相当于调用了另一个方法而已。执行的时候依然是顺序执行。
只有在调用了start方法之后,run才会有这个新的线程自己执行。
发表于 2015-01-26 13:52:40 回复(0)
俩方法都是静态的,谁先?main先。 都加了syn,啥意思?锁住了,按顺序按个来。 多线程,用的run,ok,没用start,没启动多线程,那就方法也按顺序执行。主线程控制全局,按顺序调用。
发表于 2021-10-20 08:38:13 回复(1)
弄清楚考察点,然后看清题目,对于多线程的题目要谨慎
发表于 2021-10-16 20:59:23 回复(0)
启动一个新线程要调用start(),而不是run()
发表于 2021-10-12 16:53:45 回复(0)
要想启动线程,要先调用start再调用run,只调用run启动不了线程
发表于 2021-08-30 09:45:42 回复(0)
这里是将Thead简单的看成一个类?   t.run();简单看成一个类调用方法?   不是那种start才能启动线程的逻辑?
发表于 2021-06-03 08:51:29 回复(0)
如果改成t.start().由于main线程占有锁,t线程会处于锁等待状态。最终的结果是HelloSougou
发表于 2017-05-17 21:36:33 回复(0)
其实这个题还有一个考察点是synchronized关键字,但因为并没有用start()另起一个线程,所以调用run()和调用Sogou()方法都是同一个对象,所以不会产生死锁
发表于 2015-08-16 18:38:36 回复(1)
选B,先调用线程t中的方法,然后在执行下面的语句。
发表于 2015-03-04 22:01:37 回复(0)