多个线程之间共享数据的方式

本文探讨了多线程环境下共享数据的两种典型场景:单一操作和混合操作,并提供了具体的代码示例,展示了如何通过不同方法实现数据同步与互斥。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.目标

谈到多线程共享数据,理想情况下我们希望做到“同步”和“互斥”。这是目标我们暂且把它先放到这。

二.分类

多线程共享数据通常的场景有一下两种:

场景一:

卖票,我们都买过火车票。要买火车票我们可以去车站,也可以通过代售点(或网购),但不管有多少种方式火车票的总数是一定的。

场景抽象:

对于卖票系统每个线程的核心执行的代码都相同(就是票数–)。

解决方法:

只需创建一个Runnable,这个Runnable里有那个共享数据。

代码模拟:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package 多线程共享数据;
 
public class Ticket implementsRunnable{
 
    privateint ticket = 10;
    publicvoid run() {
        while(ticket>0){
            ticket--;
            System.out.println("当前票数为:"+ticket);
        }
 
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package 多线程共享数据;
 
public class SellTicket {
 
    /**
     * @param args
     */
    publicstatic void main(String[] args) {
        Ticket t =new Ticket();
        newThread(t).start();
        newThread(t).start();
    }
 
}

 场景二:比较常见的例子,银行问题,我们对账户可以存钱也可以取钱,怎么保证这样的数据共享呢?

场景抽象:

每个线程执行的代码不同(比如上面的问题,对每个账户可以执行++操作和–操作),这时候需要用不同的Runnable对象,有如下两种方式来实现这些Runnable之间的数据共享

解决方案:
有两种方法来解决此类问题:
  • 将共享数据封装成另外一个对象中封装成另外一个对象中,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对数据进行各个操作的互斥和通信
  • 将Runnable对象作为偶一个类的内部类,共享数据作为这个类的成员变量,每个线程对共享数据的操作方法也封装在外部类,以便实现对数据的各个操作的同步和互斥,作为内部类的各个Runnable对象调用外部类的这些方法。

代码模拟:

以一道面试题为例:
“设计4个线程。,其中两个线程每次对j增加1,另外两个线程对j每次减1”
(第一种解法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyData {
     privateint j=0;
     public synchronized voidadd(){
         j++;
         System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);
     }
     public synchronized voiddec(){
         j--;
         System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);
     }
     publicint getData(){
         returnj;
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class AddRunnable implementsRunnable{
    MyData data;
    publicAddRunnable(MyData data){
        this.data= data;
    }
 
    publicvoid run() {
 
            data.add();
 
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
public class DecRunnable implementsRunnable {
    MyData data;
    publicDecRunnable(MyData data){
        this.data = data;
    }
    publicvoid run() {
 
            data.dec();
 
    }
 
}

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TestOne {
 
    /**
     * @param args
     */
    publicstatic void main(String[] args) {
        MyData data =new MyData();
        Runnable add =new AddRunnable(data);
        Runnable dec =new DecRunnable(data);
        for(inti=0;i<2;i++){
            newThread(add).start();
            newThread(dec).start();
        }
    }

解法分析:

优点:

1.这种解法代码写的有条理,简单易读,从main中很容易整理出思路

2.将数据抽象成一个类,并将对这个数据的操作作为这个类的方法,这么设计可以和容易做到同步,只要在方法上加”synchronized“

不足:

代码写的比较繁琐,需要有多个类,不是那么简洁

个人观点:为了有条理个人比较喜欢这种写法。

(第二种解法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyData {
     privateint j=0;
     public synchronized voidadd(){
         j++;
         System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);
     }
     public synchronized voiddec(){
         j--;
         System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);
     }
     publicint getData(){
         returnj;
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class TestThread {
 
    /**
     * @param args
     */
    publicstatic void main(String[] args) {
        finalMyData data = newMyData();
        for(inti=0;i<2;i++){
            newThread(new Runnable(){
 
                publicvoid run() {
                    data.add();
 
                }
 
            }).start();
            newThread(new Runnable(){
 
                publicvoid run() {
                    data.dec();
 
                }
 
            }).start();
        }
    }
 
}

解法分析:

与第一种方法的区别在于第二种方法巧妙的用了内部类共享外部类数据的思想,即把要共享的数据变得全局变量,这样就保证了操作的是同一份数据。同时内部类的方式使代码更加简洁。但是不如第一种解法条理那么清楚。

Freemake Video Converter 是一款功能强大的免费视频转换软件,支持众多的视音频、DVD 及图片格式,基本输出格式包括 AVI、MP4、WMV、MKV、3GP、DVD、Blu-ray、MP3 及 iPod、iPhone、iPad、Android 等设备格式。 Freemake Video Converter 支持 CUDA 技术,能实现更高效的视频编码,同时由于是基于.NET Framework 4开发,Freemake 的界面非常之精美、可观易用。 新版 Freemake Video Converter 在视频编辑方面有所增强,支持视频切割剪辑功能,比如切割合并视频、多段切割,以及视频旋转和视频翻转等,另外在输出配置方面有了彻底改进,附带很多的预先定义配置,并可自定义,只是它需要安装 .NET 运行库,这一点足以让很多用户望而却步了,不过它的界面和操作也确实赏心悦目。 Freemake Video Converter 功能特点 直接从超过50个网站转换在线视频 Freemake是仅有的的免费视频转换器,可以通过YouTube、Facebook、Vimeo、Dailymotion、等超过50个支持的网站,复制粘贴网址直接获取在线视频,下载YouTube到itunes中并转换成任何格式或可用装置。所有支持的网站 输出到AVI、WMV、MP4、MKV、FLV、3GP、MP3 免费转换视频到最受欢迎的视频格式。 翻录DVD 电影(未保护)为AVI、WMV、MP4、MPEG、MKV、FLV、SWF、3GP。转换视频到Flash 并直接嵌入到您的网页。使用我们的免费视频转换器转换视频和音频文件到MP3。 免费转换到iPod、iPhone、iPad、PSP、PS3、Android 为苹果、索尼和安卓设备优化视频。免费转换视频到iPod Classic、iPod Touch、iPod Nano、iPod 5G、iPhone、iPad、Sony PSP、PS2、PS3、BlackBerry、Xbox、Apple TV、Android移动设备、智能手机等。 使用CUDA和DXVA最快转换视频格式 Freemake是唯一整合CUDA和DXVA技术的免费视频转换软件,它以较少的CPU使用率进行最快的的视频转换。软件自动监测最佳转换参数并切换CUDA和DXVA的开关来获取更好的转换结果。 默认启用NVIDIA CUDA技术,能实现更高效的视频编码;它还支持Flash/SWF动画的转换。 Freemake Video Converter的缺点:如视频编辑功能相对较弱,只支持简单的剪切和翻转;输出配置也不能自定义,只能使用内置的。 Freemake Video Converter 输入格式众多,具体情况如下: 视频格式:avi, mp4, wmv, mkv, dvd, mpg, 3gp, flv, swf, tod, mts, mov, m4v, rm, qt, ts, amv, avs, bik, bnk, cavs, cdg, dpg, dv1394, dxa, ea, ffm, film, film_cpk, flc, flh, fli, flm, flt, flx, gxf, h261, h263, h264, mj2, mjpg, mkm, mtv, mxf, nc, nut, nuv, ogm, ogv, pva, r3d, rax, rms, rmx, rpl, rtsp, sdp, smk, thp, vc1, vfw, vro 音频格式:mp3, aac, ogg, wma, wav, flac, m4a, amr, au, aif, aiff, aifc, ac3, adts, alaw, apc, ape, caf, dts, gsd, gsm, mka, mlp, mmf, m4r, mp1, mp2, mpeg3, mpc, mp , m2a, nut, oma, qcp, ra, rmj, shn, tta, voc, w64, wv, xa 图片格式:bmp, jpg, gif, png, tif, anm, dpx, jpg, pam, pbm, pcx, pgm, ppm, sgi, sr, ras, tga, txd Freemake Video Converter截图
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值