java测试线程存在_java测试线程不安全简单Demo

描述场景

初学java的时候,对线程安全和不安全一直都是一个模糊的状态,接下来的这段日志我会继续深入了解多线程,以及线程安全的相关知识,

下面我用一个简单的小案例来测试一下多线程场景下导致的不安全问题.

>设计场景:

一个学校统计这个学校有多少个学生,我们每创建一个学生,学生就加1,这样我们就用这个计数来统计学校最后有多少学生.

- 学生实体类

public class Student {

private String name;

private String code;

private int age;

public static int count = 0;

public Student(){

count++;

}

public Student(String name) {

this.name = name;

count++;

}

public Student(int age) {

this.age = age;

count++;

}

public Student(String name, String code, int age) {

this.name = name;

this.code = code;

this.age = age;

count++;

}

@Override

public String toString() {

return "Student{" +

"name='" + name + '\'' +

", code='" + code + '\'' +

", age=" + age +

'}';

}

}

-线程用来表示每个班级创建多少个学生

public class StudentThread extends Thread {

@Override

public void run() {

//每个班级创建20个人,循环一次创建两个人

for (int i = 0; i < 10; i++) {

Student s = new Student();

System.out.print(Student.count+" ");

Student s1 = new Student(i);

System.out.print(Student.count+" ");

}

}

}

-测试类

public class TestThread {

public static void main(String[] args) {

//假设有两个班级,那就是要创建1个线程

for (int i = 0; i < 1; i++) {

new StudentThread().start();

}

}

}

-测试结果

28940821cf868ecaa65c5d5e718f6841.png

结果分析:从结果上来,返回的数字是我们预期想要的结果是从1-20个这么计数没错,但这个是在1个线程使用的时候.相当于此时就一个班级在统计人,

所以是不可能统计错的,那么现在又加了一个班级,结果又是怎么样的呢?

-测试类

public class TestThread {

public static void main(String[] args) {

//假设有两个班级,那就是要创建1个线程

for (int i = 0; i < 2; i++) {

new StudentThread().start();

}

}

}

-测试结果

3adde5f02102cd874b4f80477ddb6e75.png

11d984f4c0bb92f139a90485f562796b.png

结果分析:从结果可以看到,有重复的数字,说明两个线程同时的时候,会存在不清楚数据目前的状态,就会有重复的数据,

导致线程不安全.以此类推,2个线程都出现这种情况,那么增加到10个线程,那么错误率会更高.

那么我们要怎么处理,才能使线程变得安全?解决方案就是给线程加锁,在别人使用的时候,其他人不能去修改它,只能等别人使用完后才能进去操作这个线程.

-改进方法

public class StudentThread extends Thread {

@Override

public void run() {

//这是一把钥匙,只有拿到这把钥匙才能进synchronized(相当于门锁)这个方法

Boolean Flag = true;

synchronized (Flag) {

for (int i = 0; i < 10; i++) {

Student s = new Student();

System.out.print(Student.count+" ");

Student s1 = new Student(i);

System.out.print(Student.count+" ");

}

}

}

}

-测试结果

3281b8edba2c26ff28913ad16cd33f5e.png

370b0ee284c23f355976af3444832fb6.png

d669873af8b59157ec75dc45ca8ec026.png

结果分析:不过运行多少次,增加多少个线程,都不会有重复的数据,也不会乱序,因为每一个线程进来都要拿一把钥匙,这个线程进去后,其他线程在外等候,

等这个线程处理完归还钥匙,其他线程拿到钥匙才能进去.

总结

在多线程的情况下会出现线程安全问题,需要我们加锁,来保证线程的安全,单线程的情况下不会有线程安全的问题.大家还可以使用synchronized的方法来进行修改,我用的是synchronized块来加锁.

以上只是个人的见解,可能还有很多漏洞.请指教.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我可以回答这个问题。以下是一个简单的多线程安全测试 demo: ``` public class ThreadSafeTest { private static int count = ; public static void main(String[] args) { for (int i = ; i < 10; i++) { new Thread(() -> { for (int j = ; j < 100; j++) { synchronized (ThreadSafeTest.class) { count++; } } }).start(); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Count: " + count); } } ``` 这个 demo 创建了 10 个线程,每个线程会执行 100 次 count++ 操作。为了保证线程安全,我们使用了 synchronized 关键字来锁定 count 变量。最后,我们等待 1 秒钟,然后输出 count 的值。 ### 回答2: Java是一种面向对象的编程语言,它提供了丰富的多线程支持。编写一个多线程安全测试demo,可以用来测试线程环境下的线程安全性。 首先,我们需要创建一个共享资源类,这个类会在多个线程之间共享。假设我们创建一个名为SharedResource的类,其中包含一个整型变量count。我们需要保证在多个线程同时对这个count变量进行操作时,操作的结果是正确的。 接下来,我们需要编写一个测试类TestThread,这个类是一个线程类,在多个线程中会同时对SharedResource对象进行操作。我们可以让每个线程对count变量进行自增操作,然后在控制台上打印出结果。 在TestThread类中,我们需要重写run方法,并在其中编写多线程的逻辑。我们可以使用synchronized关键字来同步对共享资源的访问,确保每个线程都可以按照正确的顺序进行操作。同时,我们可以使用Thread类的sleep方法来模拟多个线程同时进行操作的情况。 最后,我们需要在主函数中创建多个TestThread的实例,并将它们作为线程启动。我们可以通过调整创建的线程数量来测试线程环境下的线程安全性。 总结起来,我们需要完成以下步骤来编写一个多线程安全测试demo: 1. 创建一个共享资源类,其中包含需要在多线程中共享的变量。 2. 编写一个线程类,重写其run方法,并在其中编写多线程的逻辑。 3. 在主函数中创建多个线程实例,并将它们作为线程启动。 4. 使用synchronized关键字来同步对共享资源的访问。 5. 使用Thread类的sleep方法来模拟多线程同时进行操作的情况。 通过以上步骤,我们可以编写一个多线程安全测试demo,来验证多线程环境下的线程安全性。 ### 回答3: 多线程安全测试是为了验证在多线程环境下,程序能否正确地处理并发访问共享资源的情况。以下是一个使用Java编写的多线程安全测试demo。 ```java import java.util.concurrent.atomic.AtomicInteger; public class ThreadSafeTestDemo { private static AtomicInteger counter = new AtomicInteger(0); public static void main(String[] args) { // 创建10个线程 for (int i = 0; i < 10; i++) { Thread thread = new Thread(new CounterIncrementer()); thread.start(); } try { // 主线程等待所有子线程执行完毕 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 打印最终的计数器值 System.out.println("Counter value: " + counter.get()); } static class CounterIncrementer implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { // 使用AtomicInteger保证线程安全的自增操作 counter.incrementAndGet(); } } } } ``` 上述代码中,我们使用`AtomicInteger`类来保证线程安全的自增操作。每个线程会执行1,000次自增操作,然后主线程等待所有子线程执行完毕,并最终打印计数器的值。 通过运行该demo,我们可以验证多线程环境下计数器的自增操作是否能够正确地进行,并且最终的计数器值是否是我们期望的结果。如果程序能够正确地保证线程安全,那么最终的计数器值应该是10,000。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值