Java多线程的一些面试心得

最近面试一直被多线程所折磨。因为之前的公司一直没有太多高并发的处理,所以对JAVA的多线程并没有太多实战经验。今天面试的时候再多线程上被虐的很惨。晚上回来赶紧写一下demo去理解一下。

事例1:

 1 public class A
 2 {
 3     public synchronized static void m1()
 4     {
 5         System.out.println("m1");
 6         try
 7         {
 8             Thread.sleep(3000);
 9         } catch (InterruptedException e)
10         {
11             // TODO Auto-generated catch block
12             e.printStackTrace();
13         }
14     }
15     public synchronized static void m2()
16     {
17         System.out.println("m2");
18         try
19         {
20             Thread.sleep(3000);
21         } catch (InterruptedException e)
22         {
23             // TODO Auto-generated catch block
24             e.printStackTrace();
25         }
26     }
27     public synchronized void m3()
28     {
29         System.out.println("m3");
30         try
31         {
32             Thread.sleep(3000);
33         }
34         catch (InterruptedException e)
35         {
36             // TODO Auto-generated catch block
37             e.printStackTrace();
38         }
39     }
40     public synchronized void m4()
41     {
42         System.out.println("m4");
43         try
44         {
45             Thread.sleep(3000);
46         } catch (InterruptedException e)
47         {
48             // TODO Auto-generated catch block
49             e.printStackTrace();
50         }
51     }
52     public void m5()
53     {
54         System.out.println("m5");
55         try
56         {
57             Thread.sleep(3000);
58         } catch (InterruptedException e)
59         {
60             // TODO Auto-generated catch block
61             e.printStackTrace();
62         }
63     }
64     public static void main(String[] args)
65     {
66         final A a1 = new A();
67         final A a2 = new A();
68         new Thread(new Runnable()
69         {
70
71             @Override
72             public void run()
73             {
74                 A.m1();
75                 A.m2();
76                 a1.m3();
77                 a1.m4();
78             }
79         },"T1").start();
80
81         new Thread(new Runnable()
82         {
83
84             @Override
85             public void run()
86             {
87                 A.m1();
88                 A.m2();
89                 a1.m3();
90                 a1.m4();
91             }
92         },"T2").start();
93     }
94 }

对于静态方法来说,他们的同步,实际上锁的是这个.class,这个类。

所以对于多个线程是无法并发访问 A.m1()和A.m1()的,也无法同时访问A.m1()和A.m2();

对于非静态方法,他们的同步,实际上锁的是这个对象的this实例。所以同时只能有一个线程去调用这个对象里面的同步方法。

由此可见:

T1访问A.m1() T2访问a1.m3(),可以并发访问

T1访问A.m2() T2访问a1.m4(),可以并发访问

T1访问a1.m3() T2访问a1.m3(),不可以并发访问,他们公用同一个this

T1访问a1.m3() T2访问a1.m4(),也不可以并发访问,他们公用同一个this

T1访问a1.m3() T2访问a2.m3(),可以并发访问,他们锁定的是两个this

T1访问a1.m3() T2访问a1.m5(),可以并发访问,m5没有被synchronized修饰

事例2:

现在我们需要编写这样一个代码:有五个txt文件,我们需要用五个线程对这5个文件进行字符统计,最后在汇总这5个文件的字符出现的次数。

  1 import java.io.FileNotFoundException;
  2 import java.io.FileReader;
  3 import java.io.IOException;
  4 import java.util.ArrayList;
  5 import java.util.HashMap;
  6 import java.util.List;
  7 import java.util.Map;
  8 import java.util.Set;
  9 import java.util.concurrent.CountDownLatch;
 10
 11
 12 class ThreadTest implements Runnable{
 13     private int num;
 14     public Map<Character, Integer> map = new HashMap<Character, Integer>(){};
 15     private CountDownLatch latch = null;
 16     public ThreadTest(int i, CountDownLatch latch)
 17     {
 18         this.num = i;
 19         this.latch = latch;
 20     }
 21
 22     @Override
 23     public void run()
 24     {
 25         FileReader fr;
 26         try
 27         {
 28             fr = new FileReader(num + ".txt");
 29         }
 30         catch (FileNotFoundException e)
 31         {
 32             System.out.println("File " + num + ".txt not find");
 33             return ;
 34         }
 35         int ch = 0;
 36         try
 37         {
 38             while((ch = fr.read())!=-1 )
 39             {
 40                 char c = (char) ch;
 41                 if ( map.containsKey(c) )
 42                 {
 43                     int count = map.get(c);
 44                     count ++;
 45                     map.put(c, count);
 46                 } else{
 47                     map.put(c, 1);
 48                 }
 49             }
 50             latch.countDown();
 51         }
 52         catch (IOException e)
 53         {
 54
 55         }
 56     }
 57 }
 58
 59 public class B
 60 {
 61     public static final int N = 5;
 62     public static void main(String[] args) throws InterruptedException
 63     {
 64         List<ThreadTest> threadTestList = new ArrayList<ThreadTest>(){};
 65         List<Thread> threadList = new ArrayList<Thread>(){};
 66         CountDownLatch latch = new CountDownLatch(N);
 67         for (int i = 0; i < N; i++)
 68         {
 69             ThreadTest threadTest = new ThreadTest(i, latch);
 70             threadTestList.add(threadTest);
 71             Thread thread = new Thread(threadTest);
 72             threadList.add(thread);
 73         }
 74         for (int i = 0; i < N; i++ )
 75         {
 76             threadList.get(i).start();
 77         }
 78         latch.await();
 79         Map<Character, Integer> result = new HashMap<Character, Integer>(){};
 80         for ( ThreadTest threadTest : threadTestList )
 81         {
 82             Set<Character> charList = threadTest.map.keySet();
 83             for (Character ch : charList)
 84             {
 85                 if ( result.containsKey(ch) )
 86                 {
 87                     Integer count = result.get(ch);
 88                     count += threadTest.map.get(ch);
 89                     result.put(ch, count);
 90                 } else
 91                 {
 92                     result.put(ch, threadTest.map.get(ch));
 93                 }
 94             }
 95         }
 96         for (Character ch : result.keySet() )
 97         {
 98             System.out.println(ch + "   " + result.get(ch));
 99         }
100     }
101
102 }

这里主要利用的是JAVA里面的CountDownLatch类。

创建CountDownLatch类时需要设定一个计数器。每当其他线程执行一次countDown方法时,计数器会减一,当计数器为0时,会唤醒所有正在执行await方法的线程。

66行执行了一次CountDownLatch类,并设置计数器为N(5)

69行在创建ThreadTest时将latch传入

50行在每个子线程执行完了统计之后会执行countDown方法

78行主线程执行await方法处于等待状态,当所有子线程执行完了countDown方法后,计数器为0,await会被唤醒,继续执行主线程的统计工作。

CountDownLatch类只是实现这种主子线程调度的其中一种方法,应该还有其他的办法。今天太晚了就先调研到这里。

2015-04-09 01:19:39

时间: 2024-10-06 23:29:31

Java多线程的一些面试心得的相关文章

最常见的15个Java多线程,并发面试问题

例如,用于DMA交易的高容量和低延迟电子交易系统通常是并发的.大多数情况下,他们专注于微秒延迟,这就是为什么拥有如何有效地最小化延迟和提高吞吐量知识是如此重要. 这些是我最喜欢的关于Java的线程面试问题.我没有提供这些线程访谈问题的答案,但我会尽可能给你一个提示.我会更新帖子就详细的答案,就像我最近在Java中发布的10个Singleton面试问题一样. 15 Java Thread Interview Questions and answers 无论如何,这里是一些常见的Java多线程和并发

Java 多线程并发编程面试笔录一览

知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该类然后实现 run 方法 推荐方式二,因为接口方式比继承方式更灵活,也减少程序间的耦合. 3.获取当前线程信息? Thread.currentThread() 4.线程的分类 线程分为守护线程.用户线程.线程初始化默认为用户线程. setDaemon(true) 将该线程标记为

java多线程心得

多并发的时候,在什么情况下必须加锁?如果不加锁会产生什么样的后果. 加锁的场景跟java的new thread和Runnable的关系是什么? 看看java的concurrentMap源码. 还有spring 的web.xml启动执行源码 spring aop http://www.cnblogs.com/FDROSE1001/p/3661895.html activemq的本质是什么? java的jms hibernate由配置文件映射到实体类的本质是什么? java反射 spring aop

JAVA多线程和并发基础面试问答(转载)

原文链接:http://www.cnblogs.com/dolphin0520/p/3932934.html 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题. Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含

JAVA多线程和并发基础面试问答

原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/ 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环

Java多线程面试15道

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题.在投资银行业务中多线程和并发是一个非常受欢迎的话题,特别是电子交易发展方面相关的.他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者有足够的Java线程与并发方面的知识,因为候选人中有很多只浮于表面.用于直接面向市场交易的高容量和低延时的电子交易系统在本质上是并发的.下面这些是我在不同时间不同地点喜欢问的Jav

JAVA多线程和并发基础面试问答【转】

JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单 一进程.线程可以被称为轻量

17、JAVA多线程和并发基础面试问答

JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/ 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(se

一个资深java面试官的“面试心得”

在公司当技术面试官几年间,从应届生到工作十几年的应聘者都遇到过.先表达一下我自己对面试的观点: 1.笔试.面试去评价一个人肯定是不够准确的,了解一个人最准确的方式就是“路遥知马力,日久见人心”.通过一.二个小时内的做题.交流,只是没有其他办法下进行的无奈之举,所以通过了面试不代表有多成功,没通过也不代表有多失败.2.好的面试官本身交谈的时候就不应当把自己一个居高临下的角色上,应当把自己和应聘者当做两个做技术的人平等的交流,把自己当作权威往往就会受到观点的角度.语言表达.工作领域的惯性的制约.3.