Java 同步关键字不';行不通 PackageThreadShareResource1; 公共类非同步1{ 私有整数和=0; 公共静态void main(字符串[]args){ 非同步1 n=新的非同步1(); n、 任务(); System.out.println(n.getSum()); } 公共同步的void sumAddOne(){ sum++; } 公开作废任务(){ 对于(int i=0;i
如果没有代码的注释部分,程序就会出现数据损坏,而不是每次运行时都是100。但是我认为synchronized关键字应该在sumAddOne方法上获得一个锁,它是我程序的关键区域,允许一个线程每次访问这个方法 我也尝试过使用ExecutorService,但它不能提供100次所有的运行Java 同步关键字不';行不通 PackageThreadShareResource1; 公共类非同步1{ 私有整数和=0; 公共静态void main(字符串[]args){ 非同步1 n=新的非同步1(); n、 任务(); System.out.println(n.getSum()); } 公共同步的void sumAddOne(){ sum++; } 公开作废任务(){ 对于(int i=0;i,java,multithreading,synchronization,Java,Multithreading,Synchronization,如果没有代码的注释部分,程序就会出现数据损坏,而不是每次运行时都是100。但是我认为synchronized关键字应该在sumAddOne方法上获得一个锁,它是我程序的关键区域,允许一个线程每次访问这个方法 我也尝试过使用ExecutorService,但它不能提供100次所有的运行 package threadShareResource1; public class NonSynchro1 { private int sum = 0; public static void
package threadShareResource1;
public class NonSynchro1 {
private int sum = 0;
public static void main(String[] args) {
NonSynchro1 n = new NonSynchro1();
n.task();
System.out.println(n.getSum());
}
public synchronized void sumAddOne(){
sum++;
}
public void task(){
for (int i = 0; i < 100; i++) {
new Thread(new Runnable(){
@Override
public void run() {
sumAddOne();
}
}).start();
/* try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} */
}
}
public int getSum() {
return sum;
}
}
公共作废任务(){
ExecutorService s=Executors.newCachedThreadPool();
对于(int i=0;i<100;i++){
s、 执行(新线程(新Runnable()){
@凌驾
公开募捐{
sumAddOne();
}
}));
}
s、 关机();
而(!s.isTerminated()){}
}
在Task()中,您可以启动100个线程(这是一个很大的数目),每个线程的总数加1
但当任务完成时,您所知道的是,100个线程正处于启动过程中。在调用println()之前不会阻塞,因此如何知道所有线程都已完成
睡眠可能“防止了损坏”,因为它给了系统时间来完成所有线程的启动
除此之外,您还可以正确使用Synchronized。在任何地方,多个线程可能会写入您需要的同一个变量,通常(简化),如果您只是在读取,则不需要该变量。synchronized关键字使用正确,问题是您没有等待线程完成。以下是一个可能的解决方案:
public void task(){
ExecutorService s = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
s.execute(new Thread(new Runnable(){
@Override
public void run() {
sumAddOne();
}
}));
}
s.shutdown();
while(!s.isTerminated()){}
}
公共类非同步1{
私有静态最终ExecutorService ExecutorService=Executors.newCachedThreadPool();
私有整数和=0;
公共静态void main(字符串[]args){
非同步1 n=新的非同步1();
n、 任务();
System.out.println(n.getSum());
executorService.shutdown();
}
公共同步的void sumAddOne(){
sum++;
}
公开作废任务(){
List callables=new ArrayList();
对于(int i=0;i<100;i++){
callables.add(()->{
sumAddOne();
返回null;
});
}
期货上市;
试一试{
futures=executorService.invokeAll(可调用项);
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
futures.forEach(未来->{
试一试{
future.get();
}捕获(ExecutionException | InterruptedException e){
抛出新的运行时异常(e);
}
});
}
公共整数getSum(){
回报金额;
}
}
首先,我们创建一个可调用的列表——一个将并行执行的函数列表
然后我们在executor服务上调用它们newCachedThreadPool
我在这里使用过,默认情况下有0个线程,它将创建尽可能多的线程来执行所有传递的可调用项,这些线程在空闲一分钟后将被终止
最后,在for each循环中,我们解析所有未来get()
调用将被阻止,直到executor服务执行该函数为止。如果在函数内部抛出异常,它也会抛出异常(如果不调用get()
,您根本看不到这种异常)
另外,当您想要优雅地终止程序时,最好关闭executor服务。在本例中,它只是main方法末尾的
executorService.shutdown()
。如果不这样做,当空闲线程被终止时,程序将在一分钟后终止。但是,如果使用不同的执行器服务,线程可能不会在空闲时终止,在这种情况下,程序将永远不会终止。为了完整性起见:下面是一个解决方案,说明如何使原始程序等待所有线程由它们完成:
它需要task
返回它创建的线程。在这种情况下,我们不需要将缓存管理器或集合的事情复杂化:一个简单的数组就可以了。下面是完整的课程:
for (Thread t : n.task())
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
公共类test1{
私有整数和=0;
公共同步的void sumAddOne(){
sum++;
}
公共线程[]任务(int n){
线程[]线程=新线程[n];
对于(int i=0;i
预期的行为是什么?您试图实现什么?测试100个线程何时使用同步访问公共变量。所有运行的结果都应该是100。你完全正确,当我使用ExecutorService
时,我忘记使用synchronized
,这就是结果不正确的原因。所以问题和你们描述的一样,比
for (Thread t : n.task())
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
public class TestSynchro1 {
private int sum = 0;
public synchronized void sumAddOne() {
sum++;
}
public Thread[] task(int n) {
Thread[] threads = new Thread[n];
for (int i = 0; i < n; i++) {
(threads[i] = new Thread(new Runnable() {
@Override
public void run() {
sumAddOne();
}
})).start();
}
return threads;
}
public static void main(String[] args) {
TestSynchro1 n = new TestSynchro1();
for (Thread t : n.task(100))
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(n.sum);
}
}