0
点赞
收藏
分享

微信扫一扫

多线程(线程组【ThreadGroup】)

Mezereon 2022-04-07 阅读 72

线程组: 把多个线程组合到一起。

  • 它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
package cn.itcast_06; public class MyRunnable implements Runnable {

    @Override public void run() { for (int x = 0; x < 100; x++) {
            System.out.println(Thread.currentThread().getName() + ":" + x);
        }
    }

}
package cn.itcast_06; /* * 线程组: 把多个线程组合到一起。
 * 它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。 */
public class ThreadGroupDemo { public static void main(String[] args) { // method1(); // 我们如何修改线程所在的组呢? // 创建一个线程组 // 创建其他线程的时候,把其他线程的组指定为我们自己新建线程组
 method2(); // t1.start(); // t2.start();
 } private static void method2() { // ThreadGroup(String name) //public ThreadGroup(String name)构造一个新线程组 //name - 新线程组的名称。
        ThreadGroup tg = new ThreadGroup("这是一个新的组");

        MyRunnable my = new MyRunnable(); // Thread(ThreadGroup group, Runnable target, String name) //将线程t1放到线程组tg中并给线程分别取名为"林青霞""刘意"
        Thread t1 = new Thread(tg, my, "林青霞");
        Thread t2 = new Thread(tg, my, "刘意"); //public final ThreadGroup getThreadGroup()返回该线程所属的线程组并获取此线程组的名称
 System.out.println(t1.getThreadGroup().getName());
        System.out.println(t2.getThreadGroup().getName()); //通过组名称设置后台线程,表示该组的线程都是后台线程
        tg.setDaemon(true);
    } private static void method1() {
        MyRunnable my = new MyRunnable(); //public Thread(Runnable target,String name)分配新的 Thread 对象 //target - 其 run 方法被调用的对象。 //name - 新线程的名称
        Thread t1 = new Thread(my, "林青霞");
        Thread t2 = new Thread(my, "刘意"); // 我不知道他们属于那个线程组,我想知道,怎么办 //public final ThreadGroup getThreadGroup()返回该线程所属的线程组 // 线程类里面的方法:public final ThreadGroup getThreadGroup()
        ThreadGroup tg1 = t1.getThreadGroup();
        ThreadGroup tg2 = t2.getThreadGroup(); // 线程组里面的方法:public final String getName()
        String name1 = tg1.getName();
        String name2 = tg2.getName();
        System.out.println(name1);
        System.out.println(name2); // 通过结果我们知道了:线程默认情况下属于main线程组 // 通过下面的测试,你应该能够看到,默任情况下,所有的线程都属于同一个组
 System.out.println(Thread.currentThread().getThreadGroup().getName());
    }
}

生产者和消费者之等待唤醒机制的代码优化

package cn.itcast_07; public class Student { private String name; private int age; private boolean flag; // 默认情况是没有数据,如果是true,说明有数据

    public synchronized void set(String name, int age) { // 如果有数据,就等待
        if (this.flag) { try { this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } // 设置数据
        this.name = name; this.age = age; // 修改标记
        this.flag = true;
        //唤醒等待的单个线程 this.notify();
    } public synchronized void get() { // 如果没有数据,就等待
        if (!this.flag) { try { this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } // 获取数据
        System.out.println(this.name + "---" + this.age); // 修改标记
        this.flag = false; this.notify();
    }
}

线程实现类—设置和获取信息

package cn.itcast_07; public class SetThread implements Runnable { private Student s; private int x = 0; public SetThread(Student s) { this.s = s;
    }

    @Override public void run() { while (true) { if (x % 2 == 0) {
                s.set("林青霞", 27);
            } else {
                s.set("刘意", 30);
            }
            x++;
        }
    }
}
package cn.itcast_07; public class GetThread implements Runnable { private Student s; public GetThread(Student s) { this.s = s;
    }

    @Override public void run() { while (true) {
            s.get();
        }
    }
}

测试

package cn.itcast_07; /* * 分析:
 *         资源类:Student    
 *         设置学生数据:SetThread(生产者)
 *         获取学生数据:GetThread(消费者)
 *         测试类:StudentDemo
 * 
 * 问题1:按照思路写代码,发现数据每次都是:null---0
 * 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个
 * 如何实现呢?
 *         在外界把这个数据创建出来,通过构造方法传递给其他的类。
 * 
 * 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题
 *         A:同一个数据出现多次
 *         B:姓名和年龄不匹配
 * 原因:
 *         A:同一个数据出现多次
 *             CPU的一点点时间片的执行权,就足够你执行很多次。
 *         B:姓名和年龄不匹配
 *             线程运行的随机性
 * 线程安全问题:
 *         A:是否是多线程环境        是
 *         B:是否有共享数据        是
 *         C:是否有多条语句操作共享数据    是
 * 解决方案:
 *         加锁。
 *         注意:
 *             A:不同种类的线程都要加锁。
 *             B:不同种类的线程加的锁必须是同一把。
 * 
 * 问题3:虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。
 * 如何实现呢?
 *         通过Java提供的等待唤醒机制解决。
 * 
 * 等待唤醒:
 *         Object类中提供了三个方法:
 *             wait():等待
 *             notify():唤醒单个线程
 *             notifyAll():唤醒所有线程
 *         为什么这些方法不定义在Thread类中呢?
 *             这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。
 *             所以,这些方法必须定义在Object类中。
 * 
 * 最终版代码中:
 *         把Student的成员变量给私有的了。
 *         把设置和获取的操作给封装成了功能,并加了同步。
 *         设置或者获取的线程里面只需要调用方法即可。 */
public class StudentDemo { public static void main(String[] args) { //创建资源
        Student s = new Student(); //设置和获取的类
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s); //线程类
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt); //启动线程
 t1.start();
        t2.start();
    }
}
举报

相关推荐

0 条评论