java多线程 读取list--动态读取list

java多线程 读取list--动态读取list的案例

 
本次介绍,我使用的是synchronized 同步代码块的关键字来读取list,在写java多线程时,一定要注意
synchronized 关键字的有效范围。
ps:
如果synchronized 关键字的代码块范围太大,可能会导致 优先获取到cpu资源的第一个线程 在满足条件的情况下 一直无法跳循环,从而使得其他线程
无法给获取到被cpu调度的机会,造成:想“多线程执行代码块”的预期-》演变成了 “单线程一路走到黑 执行代码块”的惨象,也就是让多线程的预期 实际变成了单线程了。
以下 我就用1个错误的例子,和一个正确的例子给大家介绍以下吧:

1.错误的例子:实际是单线程 执行synchronized代码块的内容

package com.cdncp.testautomation.control.conf;
import java.util.ArrayList;
import java.util.List;

public class Test_4 {
    /**
     * 多线程处理list
     *
     * @param data      数据list
     * @param threadNum 线程数
     */
    public void handleList(List<String> data, int threadNum) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            HandleThread thread = new HandleThread("线程[" + (i + 1) + "] ", data);
            thread.start();
            System.out.println("thread name:" + thread.getName());
        }

        long end = System.currentTimeMillis();
        System.out.println("time:" + (end - start));
    }

    public static void main(String[] args) {
        Test_4 test = new Test_4();
        // 准备数据
        List<String> data = new ArrayList<String>();
        for (int i = 0; i < 40; i++) {
            data.add("item" + i);
        }
        HandleThread.info = data;
        test.handleList(data, 10);
    }
}

第二个类:

package com.cdncp.testautomation.control.conf;
import java.util.List;

public class HandleThread extends Thread {
    public static List<String> info;

    private String threadName;
    private List<String> data;
    //静态钥匙
    static Object ob = "key"; //值是任意的

    public HandleThread(String threadName, List<String> data) {
        this.threadName = threadName;
        this.data = data;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (HandleThread.class) {
                try {
                   Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                if (info.size() > 0) {
                    System.out.println(this.threadName + ":  " + info.toString());
                    info.remove(info.get(0));
                } else {
                    System.out.printf("%s:票已售空 \n", getName());
                    break;
                }

            }
        }
    }
}

执行结果:

无法满足 按照我设定的线程数 去动态读取list(虽然读取数据是线程安全的,但是线程数不能按照预期创建的个数执行)

 

2.正确的例子:实现按照预定创建的 多线程 执行synchronized代码块的内容:

package com.cdncp.testautomation.control.conf;
import java.util.ArrayList;
import java.util.List;

public class Test_4 {
    /**
     * 多线程处理list
     *
     * @param data      数据list
     * @param threadNum 线程数
     */
    public void handleList(List<String> data, int threadNum) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            HandleThread thread = new HandleThread("线程[" + (i + 1) + "] ", data);
            thread.start();
            System.out.println("thread name:" + thread.getName());
        }

        long end = System.currentTimeMillis();
        System.out.println("time:" + (end - start));
    }

    public static void main(String[] args) {
        Test_4 test = new Test_4();
        // 准备数据
        List<String> data = new ArrayList<String>();
        for (int i = 0; i < 40; i++) {
            data.add("item" + i);
        }
        HandleThread.info = data;
        test.handleList(data, 10);
    }
}

第二个类:

区别就是synchronized设置的代码块范围:

 

ps:

我创建了9个线程,这里也是个线程去执行代码块,获取list中的数据!!!

 

原因分析:

如果synchronized 关键字的代码块范围太大(其实本质还是 同步代码块没写对),可能会导致 优先获取到cpu资源的第一个线程 在满足条件的情况下 一直无法跳循环,那么这个线程就一直占用cpu资源,一直执行。
synchronized 关键字的代码块的特别是:同一时间就只能有一个线程去执行,只有等这个线程执行完毕这个代码块后,资源才会被释放,然后才能让其他线程去执行这个synchronized 关键字的代码块。
案例一中,就是因为这个原因,这就从而使得其他线程(即使我创建了9个线程,其实就只要小于9个线程在执行) 无法获取到被cpu调度的机会,其他线程也就不能执行了!!!

 

posted @ 2024-04-17 15:39  苹果芒  阅读(66)  评论(0编辑  收藏  举报