• Java多线程基础学习(二)


    9. 线程安全/共享变量——同步
    当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次。这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”。
    为了解决线程安全的问题,我们可以使用“同步”来控制线程访问。当一个线程在使用这个共享资源(不仅仅是变量,还可以是集合、对象等)的时候,其他线程就无法访问。
    package threadStudy;
    
    public class ThreadSynchronizedTest {
    
        public static void main(String[] args) throws InterruptedException{
            int i=0;
            ObjA o = new ObjA(i);
            TheThread theThread1 = new TheThread(o);
            TheThread theThread2 = new TheThread(o);
            theThread1.start();
            theThread2.start();
        }
        
        static class TheThread extends Thread{
            private ObjA objA;
            public TheThread(ObjA objA){
                this.objA = objA;
            }
            public void run(){
                objA.method();
            }
        }
        
        static class ObjA{
            int i;
            public ObjA(int i){
                this.i = i;
            }
            synchronized public void method(){
                for (int j=0;j<10;j++){
                    i++;
                    System.out.println(Thread.currentThread().getName()+ ": " + i);
                    try{
                        Thread.sleep(200);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    以上述代码为例,如果加了关键字synchronized,则一个线程在使用共享资源o时,另一个线程必须等到前一个线程使用完,才能使用。

    synchronized的输出结果:

    而不加synchronized的输出结果:

     10. 容器类并发问题的同步解决方法

    JDK中提供了并发容器,可以直接帮我们解决容器类出现的并发问题。它们大部分都存在java.util.concurrent这个包中,包括:ConcurrentHashmap,CopyOnWriteArrayList,ConcurrentLinkedQueue,BlockingQueue,ConcurrentSkipListMap。下面是使用ConcurrentHashmap解决Map容器并发问题的例子:

     1 package threadStudy;
     2 
     3 import java.util.Collections;
     4 import java.util.HashMap;
     5 import java.util.Map;
     6 
     7 public class ThreadConcurrencyCollectionTest {
     8 
     9     public static void main(String[] args) {
    10         Thread thread1 = new Thread(new HashTest.AddThread(0), "T0");
    11         Thread thread2 = new Thread(new HashTest.AddThread(1), "T1");
    12         thread1.start();
    13         thread2.start();
    14 
    15     }
    16     
    17 }
    18 
    19 class HashTest{
    20     //static Map<String, String> map = new HashMap<String, String>();
    21     static Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());
    22     public static class AddThread extends Thread{
    23         private int start;
    24         public AddThread(int start){
    25             this.start = start;
    26         }
    27         public void run(){
    28             for (int i=start; i<10000; i+=2){
    29                 System.out.println(Integer.toString(i));
    30                 map.put(Integer.toString(i), Integer.toBinaryString(i));
    31             }
    32         }
    33             
    34     }
    35 }
    zni.feng@gmail.com
  • 相关阅读:
    【C语言】学习笔记9——结构struct(2)
    WPF dev 获取gridControl筛选后的数据
    WPF DEV dxc:ChartControl 柱状图
    WPF 重写ListBox(透明效果)
    WPF 后台重写 DataTemplate
    WPF 去掉Drag a column header here to group by that column
    c# 对DataTable进行分组group by
    c# ref与out用法
    WPF canvas设置旋转角度和偏移位置
    WPF 流加载
  • 原文地址:https://www.cnblogs.com/znicy/p/5681282.html
Copyright © 2020-2023  润新知