zoukankan      html  css  js  c++  java
  • 2019-06-03 Java学习日记之多线程下&GUI

    多线程下

    单例设计模式:

    保证类在内存中只有一个对象

    如何保证类在内存中只有一个对象呢?

      1、控制类的创建,不让其他类来创建本类的对象

      2、在本类中定义一个本类的对象,Singleton s

      3、提供公共的访问方式

    单例写法两种:

    1、饿汉式  开发用这种

    2、懒汉式  面试用这种

    3、第三种格式

    public class Demo1 {
        /**
         * 单例设计模式:保证类在内存中只有一个对象
         */
        public static void main(String[] args) {
            //Singleton s1 = new Singleton();
            
            Singleton s1 = Singleton.s;        //成员变量被私有,不能通过类名.调用        
            //Singleton.s = null;
            Singleton s2 = Singleton.s;
            
            System.out.println(s1 == s2);
            
            /*Singleton s1 = Singleton.getInstance();
            Singleton s2 = Singleton.getInstance();
            
            System.out.println(s1 == s2);*/
        }
    }
    /**
     * 饿汉式
     * @author clq
     *
     
     class Singleton {
         //1、私有构造方法,其他类不能访问该构造方法了
         private Singleton(){
             
         }
        //2、创建本类对象
        private static Singleton s = new Singleton();
        //3、对外提供公共的访问方法
        public static Singleton getInstance(){            //获取实例
            return s;
        }
     }*/
    
    /**
     * 懒汉式,单例的延迟加载模式
     * @author clq
     *
     */
     /*class Singleton {
         //1、私有构造方法,其他类不能访问该构造方法了
         private Singleton(){}
        //2、声明一个引用
        private static Singleton s;
        //3、对外提供公共的访问方法
        public static Singleton getInstance(){            //获取实例
            if (s == null) {
                //线程1等待,线程2等待
                s = new Singleton();
            }
            return s;
        }
     }*/
     /**
      * 饿汉式和懒汉式的区别:
      * 1、饿汉式是空间换时间,懒汉式是时间换空间
      * 2、在多线程访问是,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象
      * 
      */
    class Singleton {
         //1、私有构造方法,其他类不能访问该构造方法了
         private Singleton(){}
        //2、声明一个引用
        public static final Singleton s = new Singleton();
        
    }

    Runtime类:

    Runtime类是一个单例类

    import java.io.IOException;
    
    public class Demo2 {
    
        public static void main(String[] args) throws IOException {
            Runtime r = Runtime.getRuntime();            //获取运行时对象
            //r.exec("shutdown -s -t 300");
            r.exec("shutdown -a");
        }
    
    }

    Timer:

    Timer类:计时器

    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class Demo3 {
        public static void main(String[] args) throws InterruptedException {
            Timer t = new Timer();
            t.schedule(new MyTimerTask(), new Date(119,5,5,9,42,50),3000);
            //在指定时间安排指定任务
            //第一个参数,是安排的任务,第二个参数是执行的时间,第三个参数是过多长时间再重复执行
            while(true){
                Thread.sleep(1000);
                System.out.println(new Date());
            }
        }
    }
    class MyTimerTask extends TimerTask {
    
        @Override
        public void run() {
            System.out.println("我爱学习");
        }
        
    }

    两个线程间的通信:

    1、什么时候需要通信

    多个线程并发执行时,在默认情况下CPU是随机切换线程的

    如果我们希望他们有规律的执行,就可以使用通信,例如每个线程执行一次打印

    2、怎么通信

    如果希望线程等待,就调用wait()

    如果希望唤醒等待的线程,就调用notify()

    这两个方法必须在同步的代码中执行,并且使用同步锁对象来调用

    import java.util.FormatFlagsConversionMismatchException;
    
    public class Demo4 {
    
        public static void main(String[] args) {
            final Printer p = new Printer();
            
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            p.print1();
                        } catch (InterruptedException e) {
                            
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            p.print2();
                        } catch (InterruptedException e) {
                            
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    
    }
    //等待唤醒机制
    class Printer {
        private int flag = 1;
        public void print1() throws InterruptedException {    
            synchronized(this){
                if (flag != 1) {
                    this.wait();                    //当前线程等待
                }
                System.out.print("H");
                System.out.print("e");
                System.out.print("l");
                System.out.print("l");
                System.out.print("o");
                System.out.print("
    ");
                flag = 2;
                this.notify();                        //随机唤醒单个等待的线程            
            }
        }
    
        public void print2() throws InterruptedException {                            
            synchronized (this) {
                if (flag != 2) {
                    this.wait();
                }
                System.out.print("酷");
                System.out.print("狗");
                System.out.print("
    ");
                flag = 1;
                this.notify();
            }
        }
    
    }

    三个或三个以上间的线程通信:

    多个线程通信的问题

      notify()方法是随机唤醒一个线程

      notifyAll()方法是唤醒所有线程

      JDK5之前无法唤醒指定的一个线程

      如果多个线程之间通信,需要使用notifyAll()通知所有线程,用while来反复判断条件

    public class Demo5 {
        public static void main(String[] args) {
            final Printer2 p = new Printer2();
            new Thread() {
                public void run() {
                    while (true) {
                        try {
                            p.print1();
                        } catch (InterruptedException e) {
    
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
    
            new Thread() {
                public void run() {
                    while (true) {
                        try {
                            p.print2();
                        } catch (InterruptedException e) {
    
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
    
            new Thread() {
                public void run() {
                    while (true) {
                        try {
                            p.print3();
                        } catch (InterruptedException e) {
    
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    }
    
    class Printer2 {
        private int flag = 1;
    
        public void print1() throws InterruptedException {
            synchronized (this) {
                while (flag != 1) {
                    this.wait(); // 当前线程等待
                }
                System.out.print("H");
                System.out.print("e");
                System.out.print("l");
                System.out.print("l");
                System.out.print("o");
                System.out.print("
    ");
                flag = 2;
                // this.notify(); //随机唤醒单个等待的线程
                this.notifyAll();
            }
        }
    
        public void print2() throws InterruptedException {
            synchronized (this) {
                while (flag != 2) {
                    this.wait(); // 线程2在此等待
                }
                System.out.print("酷");
                System.out.print("狗");
                System.out.print("
    ");
                flag = 3;
                // this.notify();
                this.notifyAll();
            }
        }
    
        public void print3() throws InterruptedException {
            synchronized (this) {
                while (flag != 3) {
                    this.wait(); // 线程3在此等待,if语句是在哪里等待,就在哪里起来
                } // while循环是循环判断,每次都会判断标记
                System.out.print("m");
                System.out.print("u");
                System.out.print("s");
                System.out.print("i");
                System.out.print("c");
                System.out.print("
    ");
                flag = 1;
                // this.notify();
                this.notifyAll();
            }
        }
    
    }

    线程间的通信注意的问题:

    1、在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法

    2、为什么wait方法和notify方法定义在Object这类中?

    因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中

    3、sleep方法和wait方法的区别?

    a:sleep方法必须传入参数,参数就是时间,时间到了自动醒来

    wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待

    b:sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡

    wait方法在同步函数或者同步代码块中,释放锁

    JDK1.5的新特性互斥锁:

    1、同步

    使用ReentrantLock类的lock()和unlock()方法进行同步

    2、通信

    使用ReentrantLock类的newCondition()方法可以获取Condition对象

    需要等待的时候使用Condition的await()方法,唤醒的时候用signal()方法

    不同的线程使用不同的Condition,这样就能区分唤醒的时候找哪个线程了

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Demo6 {
        public static void main(String[] args) {
            Printer3 p = new Printer3();
            
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            p.print1();
                        } catch (InterruptedException e) {
                            
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            p.print2();
                        } catch (InterruptedException e) {
                            
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            p.print3();
                        } catch (InterruptedException e) {
                            
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    }
    class Printer3 {
        private ReentrantLock r = new ReentrantLock();
        private Condition c1 = r.newCondition();
        private Condition c2 = r.newCondition();
        private Condition c3 = r.newCondition();
        
        private int flag = 1;
        public void print1() throws InterruptedException {
            r.lock();                                    //获取锁
                if (flag != 1) {
                    c1.await();
                }
                System.out.print("H");
                System.out.print("e");
                System.out.print("l");
                System.out.print("l");
                System.out.print("o");
                System.out.print("
    ");
                flag = 2;
                // this.notify(); //随机唤醒单个等待的线程
                c2.signal();
                r.unlock();                                //释放锁
            }
        
    
        public void print2() throws InterruptedException {
            r.lock();
                if (flag != 2) {
                    c2.await();
                }
                System.out.print("酷");
                System.out.print("狗");
                System.out.print("
    ");
                flag = 3;
                // this.notify();
                c3.signal();
            r.unlock();
            }
    
        public void print3() throws InterruptedException {
            r.lock();
                if (flag != 3) {
                    c3.await();
                }
                System.out.print("m");
                System.out.print("u");
                System.out.print("s");
                System.out.print("i");
                System.out.print("c");
                System.out.print("
    ");
                flag = 1;
                // this.notify();
                c1.signal();
            r.unlock();
        }
    
    }

    线程的五种状态:

    新建,就绪,运行,阻塞,死亡

    GUI

    如何创建一个窗口并显示:

    Graphical User Interface(图形用户接口)

    package com.gui;
    
    import java.awt.Frame;
    import java.awt.Toolkit;
    
    public class Demo1 {
        public static void main(String[] args) {
            Frame f = new Frame("我的第一个窗口");
            f.setSize(400,600);                        //设置窗体大小        
            f.setLocation(500, 50);                    //设置窗体位置
            f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));
            
            f.setVisible(true);                        //设置窗体可见
        }
    }

    布局管理器:

    FlowLayout(流式布局管理器)

      从左到右的顺序排列

      Panel默认的布局管理器

    BorderLayout(边界布局管理器)

      东,南,西,北,中

      Frame默认的布局管理器

    GridLayout(网格布局管理器)

      规则的矩阵

    CardLayout(卡片布局管理器)

      选项卡

    GridBahLayout(网格包布局管理器)

      非规则的矩阵

    package com.gui;
    
    import java.awt.Button;
    import java.awt.FlowLayout;
    import java.awt.Frame;
    import java.awt.Toolkit;
    
    public class Demo1 {
        public static void main(String[] args) {
            Frame f = new Frame("我的第一个窗口");
            f.setSize(400,600);                        //设置窗体大小        
            f.setLocation(500, 50);                    //设置窗体位置
            f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));
            Button b1 = new Button("按钮");
            f.add(b1);
            f.setLayout(new FlowLayout());            //设置布局管理器
            f.setVisible(true);                        //设置窗体可见
        }
    }

    窗体监听:

    package com.gui;
    
    import java.awt.Button;
    import java.awt.FlowLayout;
    import java.awt.Frame;
    import java.awt.Toolkit;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowListener;
    
    public class Demo1 {
        public static void main(String[] args) {
            Frame f = new Frame("我的第一个窗口");
            f.setSize(400, 600); // 设置窗体大小
            f.setLocation(500, 50); // 设置窗体位置
            f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));
            Button b1 = new Button("按钮");
            f.add(b1);
            f.setLayout(new FlowLayout()); // 设置布局管理器
            // f.addWindowListener(new MyWindowAdapter());
            f.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
            f.setVisible(true); // 设置窗体可见
        }
    }

    鼠标监听:

    b1.addMouseListener(new MouseAdapter() {
                /*@Override
                public void mouseClicked(MouseEvent e) {    //单击
                    System.exit(0);
                }*/
                @Override
                public void mouseReleased(MouseEvent e) {    //释放
                    System.exit(0);
                }
            });

    键盘监听和键盘事件:

    b1.addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    //System.exit(0);
                    //System.out.println(e.getKeyCode());
                    //if (e.getKeyCode() == 32) {
                    if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                        System.exit(0);
                    }
                        
                }
            });

    动作监听:

    b2.addActionListener(new ActionListener() {            //添加动作监听,应用场景就是暂停视频和播放视频
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });

     适配器设计模式:

    a:什么是适配器

    在使用监听器的时候,需要定义一个类事件监听器接口

    通常接口中有多个方法,而程序中不一定所有的都用到,但又必须重写,这很繁琐

    适配器简化了这些操作,我们定义监听器时只要继承适配器,然后重写需要的方法即可

    b:适配器原理

    适配器就是一个类,实现了监听器接口,所有抽象方法都重写了,但是方法全是空的

    适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的

    目的就是为了简化程序员的操作,定义监听器时继承适配器,只重写需要的方法就可以了

    事件处理:

    事件:用户的一个操作

    事件源:被操作的组件

    监听器:一个自定义类的对象,实现了监听器接口,包含事件处理方法,吧监听器添加在事件源上,

    当事件发生的时候虚拟机就会自动调用监听器中的事件处理方法

      

  • 相关阅读:
    CodeForces Gym 100935G Board Game DFS
    CodeForces 493D Vasya and Chess 简单博弈
    CodeForces Gym 100935D Enormous Carpet 快速幂取模
    CodeForces Gym 100935E Pairs
    CodeForces Gym 100935C OCR (水
    CodeForces Gym 100935B Weird Cryptography
    HDU-敌兵布阵
    HDU-Minimum Inversion Number(最小逆序数)
    七月馒头
    非常可乐
  • 原文地址:https://www.cnblogs.com/clqbolg/p/10974854.html
Copyright © 2011-2022 走看看