JAVA高级应用之线程续写

代码示例:

多线程实现
/*
 * 保姆做家务
 * 保姆 来到洗衣间 衣服放入洗衣机
 * 洗衣机开始洗衣服 5次(1秒打印一次洗衣中…)
 * 然后 保姆来到客厅 扫地 12次
 * 洗衣机洗衣服 不影响保姆去客厅扫地
 * 然后 保姆去晒衣间 晒衣服 2次
 * (要求洗衣机洗完衣服 保姆也要扫完地才能去晒衣服)
 * 然后打印 家务处理完毕
 * 然后 保姆开始做 蹲 起 10次(交替 打印 蹲  起 各5次)
 * 蹲起完成后 最后打印 蹲起完成 很开心
 * 
 * 1.有思路 想清楚(把思路捋一捋)了再下笔写
 * 2.没思路 想出来啥写啥 一边写一边琢磨
 */
洗衣服类线程
package com.lanou3g.p04;

public class WashClothes implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int i = 0;
        while(i < 5) {
            SleepTimes.sleep();
            System.out.println("洗衣中......");
            i++;
        }
    }

}
等待一分钟类
package com.lanou3g.p04;

public class SleepTimes {
    public static void sleep() {
        long timeMillis = System.currentTimeMillis();
        while((System.currentTimeMillis() - timeMillis) < 1000) {
        }
    }
}
脱地类线程
package com.lanou3g.p04;

public class CleanFloor implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i = 0; i < 12; i++) {
            SleepTimes.sleep(); 
            System.out.println("扫地中.......");
        }
    }

}
晒衣服类线程
package com.lanou3g.p04;

public class SunClothes implements Runnable{

    @Override
    public void run() {

        // TODO Auto-generated method stub
        SleepTimes.sleep();
        for(int i = 0; i < 2; i++) {
            System.out.println("晒衣服中......");
        }
    }

}
保姆类
package com.lanou3g.p04;


public class BM implements Runnable{
    public  boolean flag = false;
    @Override
    public void run() {
        // TODO Auto-generated method stub

        WashClothes wClothes = new WashClothes();
        Thread tw = new Thread(wClothes);
        System.out.println("开始洗衣服");
        tw.start();

        CleanFloor cFloor = new CleanFloor();
        Thread cf = new Thread(cFloor);
        cf.start();

        try {
            tw.join();
            cf.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("地拖完了");
        SunClothes sunClothes = new SunClothes();
        Thread sc = new Thread(sunClothes);
        sc.start();

        try {
            sc.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        BM bm = new BM();
        Dun dun = new Dun(bm);
        Qi qi = new Qi(bm);
        Thread t1 = new Thread(dun);
        Thread t2 = new Thread(qi);

        t1.start();
        t2.start();
    }
}

class Dun implements Runnable{
    private int num = 0;
    private BM bm;
    public Dun() {}
    public Dun(BM bm) {
        this.bm = bm;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true) {
            synchronized (bm) {
                num++;
                if(num > 10) {
                    break;
                }
                if(bm.flag == true) {
                    try {
                        bm.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("蹲......");
                bm.flag = true;
                bm.notify();
            }
        }
    }
}

class Qi implements Runnable{
    private int num = 0;
    private BM bm;
    public Qi() {   
    }
    public Qi(BM bm) {
        this.bm = bm;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true) {
            synchronized (bm) {
                num++;
                if(num > 10) {
                    break;
                }
                if(bm.flag == false) {
                    try {
                        bm.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("起......");
                bm.flag =false;
                bm.notify();
            }
        }
    }

}
测试类
public class Test {
    public static void main(String[] args) {        
        BM bm = new BM();
        Thread t1 = new Thread(bm);
        t1.start();
    }
}

代码示例

/*
 * 键盘输入
 * 1.红色打印  
 * 2.黑色打印  
 * 根据输入数字的不同进行打印(打印"接口回调"即可)
 * 
 * 定义一个接口 
 * 接口方法: 要求可以接收一个字符串做参数
 * 
 * 定义一个功能类
 * 要求: 接收一个接口对象作为参数 利用接口对象调用接口方法
 * 
 * 定义两个类 实现接口
 * 第1个类 普通打印
 * 第2个类 错误(err)打印
 */
public class Demo01 {
    public static void main(String[] args) {
        System.out.println("请输入 1.红色 2.黑色");
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        // 创建一个接口的空对象
        Inter inter = null;
        if(num == 1) {
            // 创建打印红色类的对象
            inter = new RedPrint();
        }else {
            // 创建黑色类的对象
            inter = new BlackPrint();
        }
        // 使用功能类 安装不同的对象打印
        PrintClass.print(inter);
    //  System.out.println("打印完成");

    }
}

// 创建一个接口
interface Inter{
    public abstract void printS(String string);
}
// 创建一个功能类 专门负责打印
// 根本不用管 对象是谁 更不管 谁调用什么方法
// 只负责接收一个接口对象 调用什么方法
class PrintClass{
    // 打印 根据不同的对象 调用不同的方法
    // 多态好处:增加方法的扩展性(使用接口当参数)
    public static void print(Inter inter) {
        // 调用接口中的方法
        inter.printS("接口回调");
    }   
}

// 创建两个类 实现接口
class RedPrint implements Inter{

    @Override
    public void printS(String string) {
        // TODO Auto-generated method stub
        // 使用红色
        System.err.println(string);
    }

}
class BlackPrint implements Inter{

    @Override
    public void printS(String string) {
        System.out.println(string);
    }

}

回调代码示例

接口类
package com.lanou3g.hd;
public interface ReadFileInter {
    public abstract void readFile(String string);
}
Read类
package com.lanou3g.hd;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * 功能类
 * 抽奖
 * 图书馆(list)
 * 通讯录(map)
 * 保姆
 * 子线程读取
 * 模板
 * 装饰
 * 单例
 */
public class Read {
    // 使用接口对象作为参数
    public static void printFile(ReadFileInter inter) {
        // 开辟线程 读取文件
        new Thread(new Runnable() {

            @Override
            public void run() {
                FileInputStream fis = null;
                BufferedInputStream bos = null;
                // TODO Auto-generated method stub
                try {
                    fis = new FileInputStream("/Users/lanou/Desktop/test3/kkk.txt");
                    bos = new BufferedInputStream(fis);
                    int len = 0;
                    byte[] b = new byte[1024];
                    while((len = bos.read(b)) != -1) {
                        inter.readFile(new String(b, 0, len));
                    }
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    bos.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }).start();
    }
}
测试类
package com.lanou3g.hd;
// 利用接口实现 主线程处理逻辑
// 子线程 去读取文件 并打印
public class Demo02 {
    public static void main(String[] args) {
        System.out.println("主线程实现逻辑一......");
        // 开辟子线程 去读取文件 
        // 使用匿名对象方式传参数
        Read.printFile(new ReadFileInter() {
            // 匿名对象重写的方法
            @Override
            public void readFile(String string) {
                // TODO Auto-generated method stub
                // 打印读取完的文件
                System.out.println(string);
            }
        });
        System.out.println("主线程实现逻辑一......");
    }
}

join方法

谁调用jion方法 谁就先执行完毕
public class p03 {
    public static void main(String[] args) throws InterruptedException {
        ImplRunnable implRunnable = new ImplRunnable();
        Thread thread = new Thread(implRunnable);
        thread.start();
        thread.join();
        for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            System.out.println("我是主线程 线程");
        }
    }
}
class ImplRunnable implements Runnable{
    @Override
    public void run() {
        // TODO Auto-generated method stub

        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("我是子线程" + " " + i);
        }
    }   
}

volatile

当不同线程中用到同一变量时,如
果某一线程中,变量的值发生变化,使用此关键字可以同步不同线程内此变量的值.
package com.lanou3g;

public class Demo04 {
    public static void main(String[] args) {
        VolRunnable runnable = new VolRunnable();
        Thread t1 = new Thread(runnable);
        t1.start();
        // 写个线程卡主循环
        // 子线程修改的值 没有同步到主线程中
        while(!runnable.isOver) {   
        }
        System.out.println("主线程结束了");
    }

}
class VolRunnable implements Runnable{
    // volatile关键字 可以把线程中的值 修改后 立即同步出去(更新)
    public volatile boolean isOver = false;
    int num = 0;
    @Override
    public void run() {
        while(!isOver) {
            num++;
            // 把线程的执行时间加大
            // 防止上面 还没有执行到循环处 这里的值就已经改了
            // 执行到循环处 这里的值还没有改
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + " " + num);

            if(num > 5) {
                isOver = true;  
            }
        }
    }

}
理解
当子线程中没有加sleep方法 和 volatile关键字时,子线程执行过快,在主线程还没有执行到while语句时,isOver的值已经更改
变成了true,这时主线程中的while语句中的条件为false,不会进去循环,因此没有卡主线程
执行结果:Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
主线程结束了
会直接结束
当子线程中加入sleep方法,没有加volatile关键字时,大大的拖延了子线程的执行时间,使主线程执行到while语句时,
子线程中的isOver的值没有来得及更改,还是false,这时主线程中while中的条件便是true,进入循环,卡主了线程,一直在while循环中
当加入volatile修饰时,不管有没有sleep方法,isOver的值会立刻被刷新出去,while每次循环都会判断循环条件,因此主线程会顺利借宿,不会卡主
package com.lanou3g;
/*
 * 开启2个线程
 * 一个叫线程A
 * 一个叫线程B
 * 要求 
 * 先输入5遍  我是线程A
 * 再输出5遍  我是线程B
 */
public class Demo06 {
    public static void main(String[] args) {
        ABRunnable volRun = new ABRunnable();
        Thread tA = new Thread(volRun, "线程A");
        Thread tB = new Thread(volRun, "线程B");
        /*
         * 线程A先进来
         * 直接打印 唤醒(但是没有线程在等待)
         * 线程B再进来 进入等待-----
         * 解决方法
         * B再进来 不进入等待 直接打印就完事了
         * 
         * 线程B先进来
         *  先入等待 把锁换回去
         *  线程A再进来 直接打印
         *  唤醒线程B  线程B打印
         */
        tA.start();
        tB.start();
    }
}
class ABRunnable implements Runnable{
    // 利用标记 解决A先进来的情况
    /*
     * 如果A先进来 直接打印 改变标记值
     * 让B再进来的时候 不去等待
     * @see java.lang.Runnable#run()
     */
    private boolean flag = false;
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        // TODO Auto-generated method stub
        // 保证一个线程没打印完,另一个线程不能进去
        synchronized (this) {
            // 判断如果是B 就让B进入等待状态(wait()状态)
            if(name.equals("线程B")  && flag == false) {
                try {
                    // 调用wait方法 进入等待
                    // 注意:使用锁对象去调用
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            for (int i = 0; i < 5; i++) {
                System.out.println("我是 " + name);
            }
            // 等A打印完 需要唤醒等待中的线程
            // 注意wait和notify一般成对出现 都是使用锁对象调用
            // notify随机唤醒等待中的线程中的一个
            // notifyAll随机唤醒所有等待的线程
            if(name.equals("线程A")) {
                // 说明一会进来的线程B 线程B就不要等待了
                flag = true;
            }
            this.notify();
        }

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值