Java学习日志Day23_龟兔赛跑_线程组与线程池_定时器_设计模式

一、龟兔赛跑案例

/**
 * 龟兔赛跑
 * 跑道---作为资源类
 */
public class Race  implements Runnable{
    //当类一加载的时候,定义静态变量
    //胜利者
    private  static String winner = null ;
    //兔子和乌龟都要执行这个run
    @Override
    public void run() {
        //for循环:表示步数1-100步
        for(int x = 1 ; x <= 100 ; x ++){

            //真实故事中:兔子要睡觉的,模拟兔子睡觉
            if(Thread.currentThread().getName().equals("兔子") && (x % 10 ==0 )){
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //定义一个定义比赛结束的方法
            boolean flag = gameOver(x) ;
            if(flag){
                break ;
            }
            System.out.println(Thread.currentThread().getName()+"跑了====>"+x+"步");
        }
    }

    //比赛结束的方法
    private boolean gameOver(int step) {//步数  x
        //情况1:如果当前winner不等于null,存在胜利者,比赛结束
        if(winner!=null){
            return true ;
        }{
           //情况2: 判断如果当前step>=100 比赛也要结束
            if(step>=100){
                winner = Thread.currentThread().getName() ;
                System.out.println("winner is:"+winner);
                return true ;
            }
        }
        return false ;
    }

    //用户线程
    public static void main(String[] args) {
        //创建一个资源共享类
        Race race = new Race() ;
        //创建线程类对象
        Thread t1 = new Thread(race,"兔子") ;
        Thread t2 = new Thread(race,"乌龟") ;

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

代理真正用途

举例:
public class Student {

  private   String name ;
  private  int age ;
  private   boolean flag ;

  //定义一个功能:给学生赋值(产生数据)
    public synchronized void set(String name,int age){ //同步方法  锁对象:this

            //如果生产者有数据,等待消费者使用数据
            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();
    }
}

public class SetThread implements  Runnable {
    private Student s ;
    public SetThread(Student s){
        this.s = s ;
    }

    int x  = 0 ;

    @Override
    public void run() {
        //模拟生产者不断产生数据
        while(true){

            if(x % 2 ==0){
                /*s.name = "高圆圆" ;
                s.age = 41 ;*/
                s.set("高圆圆",41);
            }else{
             /*   s.name ="赵又廷";
                s.age = 45 ;*/
                s.set("耿明刚",26);
            }
            x ++;
        }
    }
}

public class GetThread implements Runnable {

    private Student s ;
    public GetThread(Student s ){
        this.s  = s ;
    }
    @Override
    public void run() {
        //模拟消费者不断使用数据
        while(true){
            s.get();

        }
    }
}

/**
 * Java中等待唤醒机制
 * SetThread:生产者资源类
 * GetThrread:消费者资源类
 * Student:学生
 */
public class ThreadDemo {
    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();
    }
}

二、线程组

线程组 ThreadGroup 线程组表示一个线程的集合
Thread类中方法:
public final ThreadGroup getThreadGroup():获取当前所有线程的默认线程组

ThreadGroup
public final String getName() :获取默认的线程组名称: (默认就是main)

构造方法:
ThreadGroup(String name):构造一个新的名称的线程组
所有的线程默认的线程组就是main线程(用户线程)

举例:
public class MyThread extends  Thread {

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

public class ThreadGroupDemo {
    public static void main(String[] args) {
        //method() ;
        method2() ;
    }

    //设置线程组名称
    private static void method2() {
//        ThreadGroup(String name):构造一个新的名称的线程组
          ThreadGroup tg = new ThreadGroup("myMain") ;
          //创建线程类对象:可以将线程组对象作为参数传递
        //public Thread(ThreadGroup group,String name)
        Thread t1 = new Thread(tg,"线程1") ;
        Thread t2 = new Thread(tg,"线程2") ;

        System.out.println(t1.getThreadGroup().getName());
        System.out.println(t2.getThreadGroup().getName());
    }

    private static void method() {
        //创建两个线程类对象

        MyThread my1 = new MyThread() ;
        MyThread my2 = new MyThread() ;

        //获取对应的线程组名称
        ThreadGroup tg1 = my1.getThreadGroup();
        String name = tg1.getName();
        ThreadGroup tg2 = my2.getThreadGroup();
        String name2 = tg2.getName();
        System.out.println(name);
        System.out.println(name2);
    }
}

三、线程池

  1. 线程池的使用:
    1)接口:ExecutorService :跟踪一个或者多个异步任务
    2)如何实例化---->Executors.newFixedThreadPool(int) 工厂方法:

  2. Executors:工厂类
    提供创建线程池对象的方法
    public static ExecutorService newFixedThreadPool(int nThreads)

  3. ExecutorService
    方法:
    Future<?> submit(Runnable task) :通过线程池提交异步任务
    Future submit(Callable task):提交异步任务
    Future:异步任务计算的结果!

第三种方式:线程池实现---->还是自定义一个类 实现Runnable接口
引入线程池
线程池的七大参数

举例:
public class MyRunnable implements  Runnable{
    @Override
    public void run() {

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

 /* MyCallabe:等待需要被线程池提交的异步任务
 */
public class MyCallable implements Callable<Object> {

    //call方法:本身要计算的结果
    @Override
    public Object call() throws Exception {
        for(int x = 0 ; x <100 ; x ++ ){
            System.out.println(Thread.currentThread().getName()+":"+x);
        }
        return null;
    }
}

public class ThreadDemo {
    public static void main(String[] args) {

       /* new Thread(){
            @Override
            public void run() {

            }
        }.start();*/
        //创建一个线程池:静态工厂模式
        ExecutorService pool = Executors.newFixedThreadPool(2);

        //提交异步任务
        // Future<?> submit(Runnable task) :通过线程池提交异步任务
       /* pool.submit(new MyRunnable()) ;
        pool.submit(new MyRunnable()) ;*/
       //Callable要比Runnable接口更好
        //可以跟踪具体的异常错误(如果执行过程中,线程出现异常,可以跟踪异常信息!)
       pool.submit(new MyCallable()) ;
       pool.submit(new MyCallable()) ;

        //使用完毕,关闭线程池--将底层产生的线程归还线程池中
        pool.shutdown();
    }
}
举例:
/* 两条线程分别线程的求和
 */
public class MyCallable implements Callable<Integer> {

    private int number ;
    public MyCallable(int number){
        this.number  = number ;
    }

    //call方法:异步结果结果:它的返回值需要和Callable泛型的数据类型一致
    //最终结果变量:
    int sum = 0 ;
    @Override
    public Integer call() throws Exception {  //就是线程执行的耗时操作 类似于 Runnable的run方法
        for(int x = 1 ; x <= number; x ++){
            sum+=x ;
        }
        return sum;
    }
}

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建存有2条线程的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        //Future:接口:异步计算的结果
        Future<Integer> f1 = executorService.submit(new MyCallable(100));
        Future<Integer> f2 = executorService.submit(new MyCallable(200));
        //V get():获取结果值
        Integer i1 = f1.get();
        Integer i2 = f2.get();
        System.out.println(i1);
        System.out.println(i2);
    }
}

四、定时器

java.util.Timer:定时器 :有线程安排执行务执行一次,或者定期重复执行。
构造方法:
public Timer() 无参构造方法
成员方法
public void cancel():取消定时器
public void schedule(TimerTask task,Date time) :在指定日期时间内执行这个任务
public void schedule(TimerTask task,long delay):在指定的延迟时间后执行task任务(时间:毫秒)
public void schedule(TimerTask task,
long delay,
long period) :在指定的delay延迟时间后开始重复时间间隔period来执行task任务
需求:
在某天的18点将 d://demo文件夹 中的所有的带后缀为.java文件删除掉! (Timer+io流+递归:综合使用)

public class TimerDemo {

    public static void main(String[] args) {
        //创建一个定时器
        Timer timer  = new Timer() ;
        //   public void cancel():取消定时器

        //参数1:定时任务:抽象类,定义子类继承自TimerTask
       // timer.schedule(new MyTask(timer),3000); :3秒后执行一次这个任务

      /*  public void schedule(TimerTask task,
                     long delay,
                       long period) :在指定的delay延迟时间后开始重复时间间隔period来执行task任务*/

      timer.schedule(new MyTask(timer),2000,3000);
    }
}

//定时任务
class MyTask extends TimerTask{ //TimerTask实现Runnable接口         ---会使用同步机制
    private Timer t ;
    public MyTask(Timer t){
        this.t = t ;
    }

    @Override
    public void run() {

        System.out.println("bom...");
        //关闭定时器
        //t.cancel() ;
    }
}

五、设计模式

  1. Java设计原则:
    单一职责
    接口分离
    开闭原则
    依赖注入原则(依赖于抽象类或者接口,而不依赖具体类实现)
    面向对象设计思想
    单一职责、开闭原则
    里氏替换、依赖注入、接口分离
    迪米特原则
    常见设计模式
    设计模式
    简单工厂模式
举例:
public class Animal {

    public void eat(){
        System.out.println("动物都需要吃");
    }
    public void sleep(){
        System.out.println("动物都需要休息");
    }
}

public class Cat extends  Animal {


        public void eat(){
            System.out.println("i can eat and eat mouse");
        }

        public void sleep(){
            System.out.println("i can sleep ...");
        }
}

public class Dog  extends  Animal{

    public void eat(){
        System.out.println("i can eat and eat meat");
    }
    public void sleep() {
        System.out.println("i can sleep");
    }
}

public class Pig extends Animal {

    @Override
    public void eat() {
        System.out.println("eat");
    }

    @Override
    public void sleep() {
        System.out.println("sleep");
    }
}

public class AnimalFactory {
    //构造方法私有化
    private AnimalFactory(){ //外界不能创建当前类对象

    }

    //静态方法
    //创建猫的实例
 /*   public static Cat createCat(){

        return new Cat() ;
    }

    //创建狗的实例
    public static Dog createDog(){
        return new Dog() ;
    }

    //创建猪的实例
    public static Pig createPig(){
        return new Pig() ;
    }*/

 //优化:利用多态:提供功能扩展
    public static Animal createAnimal(String type){
        if(type.equals("dog")){
            return new Dog() ;
        }else if(type.equals("cat")){
            return new Cat() ;
        }else if(type.equals("pig")){
            return new Pig() ;
        }else{
            System.out.println("对不起,工厂类没有提供者动物的实例创建!");
        }
        return null ;
    }
}

/* 创建型设计模式:对象的创建
 * Java提供:简单工厂模式 ---静态工厂方法模式
 * 优点:不需要具体类创建具体实例,通过工厂类创建
 *
 * 弊端:一旦有一个新的类型增,修改工厂类!
 *
 * 需要提供一个工厂类,负责具体的实例的创建
 */
public class Test {

    public static void main(String[] args) {

        //创建猫
        Cat cat = new Cat() ;
        cat.eat();
        cat.sleep();
        //狗
        Dog dog = new Dog() ;
        dog.eat();
        dog.sleep();

        System.out.println("------------------------");

        //提供工厂类创建具体的动物实例
       /* Cat c1 = AnimalFactory.createCat();
        c1.eat();
        c1.sleep();
        Dog d = AnimalFactory.createDog() ;
        d.eat();
        d.sleep();*/

       //优化之后
        Animal animal = AnimalFactory.createAnimal("dog"); //父类引用指向子类对象
        animal.eat();
        animal.sleep();
        animal = AnimalFactory.createAnimal("cat") ;
        animal.eat();
        animal.sleep();
    }
}

工厂模式总结

举例:
public  abstract  class Animal {

    public abstract  void eat() ;//吃
}

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("够吃骨头...");
    }
}

public interface Factory { //工厂接口


    //创建动物的实例
    public abstract Animal  createAnimal() ;
}

public class CatFactory implements Factory{
    @Override
    public Animal createAnimal() {
        return new Cat() ;
    }
}

public class DogFactoy implements Factory {

    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}

/* 工厂方法模式:
 *      对象创建的工作:有一个接口完成
 *      接口的子实现类---->创建具体实例的工厂类
 *      优点:面向接口编程:  结构非常清晰,维护起来容易
 *      弊端:代码量增加了,需要编写额外的工厂类...
 */
public class Test {
    public static void main(String[] args) {

        //没有使用工厂方法模式
        //抽象类多态
        Animal a = new Cat();
        a.eat();
        a = new Dog() ;
        a.eat();

        System.out.println("-----------------------------------");

        //猫的工厂类
        Factory f = new CatFactory() ;
        Animal animal = f.createAnimal(); //new Cat()
        animal.eat();


        f = new DogFactoy() ;
        Animal an = f.createAnimal();
        an.eat();
    }
}

单例设计模式
分类
懒加载和立即加载

public class Student {

    //创建该类实例---(类的实例变量)
//    public static Student s = new Student() ;
    private static Student s = new Student() ;
    private Student(){} //外界不能创建对象

    //提供对外的公共访问方法:静态的
    public static Student getStudent(){
        return s ;
    }
}

/* 创建型设计模式之单例
 *
 * 单例:
 *      在加载某个类的时候,内存中始终只有一个对象!(该类对象自动创建)
 *
 *      两种:
 *          饿汉式:特点  永远不会出现问题的单例模式!
 *              在加载这个类的时候,就已经在内存中创建了一个对象!
 *              1)自定义一个类(具体类)
 *              2)成员位置:创建当前类的实例
 *              3)提供私有的构造方法:外界不能够创建它
 *              4)对外提供公共的访问方法:静态的,返回值当前类本身
 *
 *          懒汉式:可能出现问题的单例模式
 *                   1)自定义一个类(具体类)
 *                   2)成员位置:声明类型的变量
 *                   3)构造方法私有化
 *                   4)提供对外的公共访问方法:
 *                          需要判断:当前如果没有对象,new 对象
 *
 *                          存在懒加载或者延迟加载!
 *                          可能出现多线程 安全问题:
 *
 *                         如何解决
 *                              加同步锁
 *
 *
 */
public class Tests {

    public static void main(String[] args) {
        /*Student s  =new Student() ;
        Student s2 = new Student() ;
        System.out.println(s==s2) ;//false
        System.out.println(s.getClass()==s2.getClass());//true*/
        //getClass()---->class 包名.类名

       // Student.s = null ; //被外界更改掉

        Student s1 = Student.getStudent();
        Student s2 = Student.getStudent();
        System.out.println(s1==s2);

        System.out.println("-----------------");
        Programmer p1 = Programmer.getPro();
        Programmer p2 = Programmer.getPro();
        Programmer p3 = Programmer.getPro();

        System.out.println(p1==p2);
        System.out.println(p1==p3);

    }
}

public class Programmer {
    private static Programmer pro = null ;
    private Programmer(){}

    //p1,p2,p3
    //对外公共访问方法
    /*public static Programmer getPro(){
        synchronized (Programmer.class){
            if(pro ==null){
                pro = new Programmer() ;
            }
            return pro ;
        }

    }*/
    public synchronized static Programmer getPro(){//静态同步方法:锁对象:当前类名.class属性
            if(pro ==null){
                pro = new Programmer() ;
            }
            return pro ;
    }
}
举例:
/* 标准单例模式之饿汉式:Runtime
 * 个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接
 */
public class RuntTimeDemo {

    public static void main(String[] args) throws IOException {

        Runtime runtime = Runtime.getRuntime();
      //  Runtime runtime2 = Runtime.getRuntime();
        //System.out.println(runtime==runtime2);
        int cpuSize = runtime.availableProcessors();
        System.out.println(cpuSize);
        runtime.exec("notepad") ;
        runtime.exec("mspaint") ;
        runtime.exec("calc") ;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

igfff

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值