码迷,mamicode.com
首页 > 编程语言 > 详细

Java多线程的一些面试心得

时间:2015-04-09 06:08:53      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

最近面试一直被多线程所折磨。因为之前的公司一直没有太多高并发的处理,所以对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

Java多线程的一些面试心得

标签:

原文地址:http://www.cnblogs.com/welshu/p/4406052.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!