Java 7之多线程第3篇 - 笔试、面试常见线程问题
2013-11-24 20:34
771 查看
如下的几个问题是笔试、面试中经常出现的,也是典型的线程问题。
1、main方法启动不同进程
如上的两个main方法会各自启动一个进程,而进程的堆是不共享的,所以互不干扰。a.a的值为7,而b.a的值仍为6
2、多线程与同步
多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方面有两种,分别是synchronized,wait与notify
3、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法
分几种情况:1.其他方法前是否加了synchronized关键字,如果没加,则能。2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。所以这里是可以进入的
4、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1
5、子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次(这个题目类似与生产者-消费者的实现逻辑)
6、查看线程运行的结果
t2 end
t1 end
1、main方法启动不同进程
public class A{ // 定义该类的静态Field public static int a = 6; } public class ATest1{ public static void main(String[] args){ // 创建A类的实例 A a = new A(); // 让a实例的a Field的值自加 a.a ++; System.out.println(a.a); } } public class ATest2{ public static void main(String[] args) { // 创建A类的实例 A b = new A(); // 输出b实例的a Field的值 System.out.println(b.a); } }
如上的两个main方法会各自启动一个进程,而进程的堆是不共享的,所以互不干扰。a.a的值为7,而b.a的值仍为6
2、多线程与同步
多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方面有两种,分别是synchronized,wait与notify
3、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法
分几种情况:1.其他方法前是否加了synchronized关键字,如果没加,则能。2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。所以这里是可以进入的
4、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1
public class test3 { private int j; public static void main(String args[]) { test3 tt = new test3(); Inc inc = tt.new Inc(); Dec dec = tt.new Dec(); for (int i = 0; i < 2; i++) { Thread t = new Thread(inc); t.start(); t = new Thread(dec); t.start(); } } private synchronized void inc() { j++; System.out.println(Thread.currentThread().getName() + "-inc:" + j); } private synchronized void dec() { j--; System.out.println(Thread.currentThread().getName() + "-dec:" + j); } class Inc implements Runnable { public void run() { for (int i = 0; i < 100; i++) { inc(); } } } class Dec implements Runnable { public void run() { for (int i = 0; i < 100; i++) { dec(); } } } }或者也可以使用如下的实现方式:
class JManager { private int j = 0; public synchronized void subtract() { j--; } public synchronized void accumulate() { j++; } } class A { JManager j = new JManager(); void main() { new A().call(); } void call() { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { public void run() { while (true) { j.accumulate(); } } }).start(); new Thread(new Runnable() { public void run() { while (true) { j.subtract(); } } }).start(); } } }
5、子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次(这个题目类似与生产者-消费者的实现逻辑)
public class test3 { private static boolean bShouldMain = false; public static void main(String[] args) { new Thread(new Runnable() { public void run() { for (int i = 0; i < 50; i++) { synchronized (test3.class) { if (bShouldMain) { try { test3.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 0; j < 10; j++) { System.out.println(Thread.currentThread().getName() + "i=" + i + ",j=" + j); } bShouldMain = true; test3.class.notify(); } } } }).start(); for (int i = 0; i < 50; i++) { synchronized (test3.class) { if (!bShouldMain) { try { test3.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 0; j < 5; j++) { System.out.println(Thread.currentThread().getName() + "i=" + i + ",j=" + j); } bShouldMain = false; test3.class.notify(); } } } }或者还可以使用线程池来实现。具体代码如下:
import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.Condition; public class test3 { private static Lock lock = new ReentrantLock(); private static Condition subThreadCondition = lock.newCondition(); private static boolean bBhouldSubThread = false; public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(3); threadPool.execute(new Runnable() { public void run() { for (int i = 0; i < 50; i++) { lock.lock(); try { if (!bBhouldSubThread) subThreadCondition.await(); for (int j = 0; j < 10; j++) { System.out.println(Thread.currentThread().getName() + ",j=" + j); } bBhouldSubThread = false; subThreadCondition.signal(); } catch (Exception e) { } finally { lock.unlock(); } } } }); threadPool.shutdown(); for (int i = 0; i < 50; i++) { lock.lock(); try { if (bBhouldSubThread) subThreadCondition.await(); for (int j = 0; j < 10; j++) { System.out.println(Thread.currentThread().getName() + ",j=" + j); } bBhouldSubThread = true; subThreadCondition.signal(); } catch (Exception e) { } finally { lock.unlock(); } } } }
6、查看线程运行的结果
public static void main(String[] args) throws InterruptedException { final Object obj = new Object(); // 两个线程使用同一个锁 Thread t1 = new Thread() { public void run() { synchronized (obj) { try { obj.wait(); // 变为等待线程,下面的代码不会被执行,锁已经让出去了 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end"); } } }; t1.start(); Thread.sleep(1000); // 为了保证让第一个线程先启动 Thread t2 = new Thread() { public void run() { synchronized (obj) { obj.notifyAll(); // 唤醒所有的等待线程,但是并不会让出锁,所以下面的程序会继续执行 System.out.println("t2 end"); } } }; t2.start(); }最后运行的结果如下:
t2 end
t1 end
相关文章推荐
- JAVA基础笔试、面试常见问题集合
- JAVA -- JAVA基础笔试、面试常见问题集合
- java线程问题小结-----常见面试问题
- java基础:常见的概念问题,面试笔试可能会遇到哟
- Java程序基础测试 基础笔试、面试常见问题集合
- JAVA基础笔试、面试常见问题集合
- SQL Server DBA常见面试 笔试问题(转)
- 面试java高级工程师、项目经理等的常见问题
- java中最常见的面试问题<1>
- 125条常见的java面试笔试题大汇总
- java线程同步问题——由腾讯笔试题引发的风波
- 面试java高级工程师、项目经理等的常见问题 .
- 线程常见的笔试问题
- java面试常见问题
- java面试常见问题
- java面试常见问题(2)
- 校招笔试面试中IP地址常见问题总结
- 125条常见的java面试笔试题汇总(四)
- JAVA面试常见问题
- 面试十大常见Java String问题