线程组: 把多个线程组合到一起。
* 它可以对一批线程进行分类管理,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(); } }
来源:https://www.cnblogs.com/ztg-java-xuexi/p/16104092.html
本站部分图文来源于网络,如有侵权请联系删除。