14 多线程,gui

多线程:
并行与并发:
并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)
并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间
间隔较短,使人感觉两个任务都在运行。

JVM的启动是多线程的吗?
    JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。

多线程程序实现的方式1:
继承Thread
    * 定义类继承Thread
    * 重写run方法
    * 把新线程要做的事写在run方法中
    * 创建线程对象
    * 开启新线程, 内部会自动执行run方法

多线程程序实现的方式2:
实现Runnable
    * 定义类实现Runnable接口
    * 实现run方法
    * 把新线程要做的事写在run方法中
    * 创建自定义的Runnable的子类对象
    * 创建Thread对象, 传入Runnable
    * 调用start()开启新线程, 内部会自动调用Runnable的run()方法

public class Demo1_Thread {

    public static void main(String[] args) {
        // 多线程程序实现
//        new MyThread().start();
        
        new Thread(new MyRunnable()).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("bbbbbbbbbbbb");
        }
    }
}
class MyThread extends Thread{
    // 方式1
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("aaaaaaaaaaaaa");
        }
    }
}
class MyRunnable implements Runnable{
    // 方式2
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("aaaaaaaaaaaaa");
        }
    }
}

 

实现Runnable的原理
    Thread类的构造函数,传递了Runnable接口的引用
    通过init()方法找到传递的target给成员变量的target赋值
    查看run方法,发现run方法中有判断,如果target不为null就会调用Runnable接口子类对象
的run方法

两种方式的区别:
    继承Thread : 由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法
    实现Runnable : 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()
方法时内部判断成员变量Runnable的引用是否为空, 不为空编译时看的是Runnable的run(),运行时执行
的是子类的run()方法
    
继承Thread
    好处:可以直接使用Thread类中的方法,代码简单
     弊端:如果已经有了父类,就不能用这种方法
实现Runnable接口:
    好处:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是
可以多实现的
    弊端:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码
复杂

匿名内部类实现线程的两种方式:

public class Demo2_Thread {

    public static void main(String[] args) {
        // 匿名内部类实现线程的两种方式
        new Thread() {
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println("aaaa");
                }
            }
        }.start();
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println("bbbb");
                }
                
            }
        }).start();
    }

}

 


获取名字和设置名字:
* 1.获取名字
    * 通过getName()方法获取线程对象的名字  //this.getName()
* 2.设置名字
    * 通过构造函数可以传入String类型的名字 //new Thread("xxx")
    * 通过setName(String)方法可以设置线程对象的名字 //t1.setName("xxx")// this.setName
("xxx")

获取当前线程的对象:
* Thread.currentThread(), 主线程也可以获取

休眠线程:
* Thread.sleep(毫秒,纳秒)

守护线程setDaemon:

public class Demo3_Daemon {

    public static void main(String[] args) {
        //setDaemon(), 设置一个线程为守护线程,
        //该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出
        Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i < 2; i++) {                    
                    System.out.println(getName

()+"aaaaaaaaaaaaaaaaaaaa");
                }
            }
        };
        Thread t2 = new Thread() {
            public void run() {
                for (int i = 0; i < 20; i++) {                    
                    System.out.println(getName()+"bbb");
                }
            }
        };
        t2.setDaemon(true); //t1结束,t2会随之结束
        t1.start();
        t2.start();
    }

}


join:

public class Demo4_Join {

    public static void main(String[] args) {
        //join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
        // join(int), 可以等待指定的毫秒之后继续
        final Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i <10; i++) {                    
                    System.out.println(getName

()+"aaaaaaaaaaaaaaaaaaaa");
                }
            }
        };
        Thread t2 = new Thread() {
            public void run() {
                for (int i = 0; i < 20; i++) {    
                    if (i==2) {
                        try {
                            t1.join();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(getName()+"bbb");
                }
            }
        };
        t1.start();
        t2.start();
    }

}


yield:

public class Demo5_Yield {

    public static void main(String[] args) {
        // yield让出cpu
        new MyThead().start();
        new MyThead().start();
    }

}
class MyThead extends Thread{
    public void run() {
        for (int i = 0; i <1000; i++) {        
            if (i%10==0) {
                Thread.yield();
            }
            System.out.println(getName()+i);
        }
    }
}


setPriority()设置线程的优先级  1~10
同步:

public class Demo6_synchronized {
    /*//同步
        当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切

换到其他线程工作. 这时就需要同步.
        如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前,

不会执行另外一段代码.
    同步代码块
        使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
        多个同步代码块如果使用相同的锁对象, 那么他们就是同步的*/
    public static void main(String[] args) {
        Object lock = new Object(); ////锁对象可以是任意对象,需要保证是同一把锁,不

能用匿名对象
        Printer printer = new Printer();
        synchronized (lock) {
            new Thread() {
                public void run() {
                    for (int i = 0; i < 100; i++) {                

        
                        printer.print1();
                    }
                }
            }.start();
        }
        synchronized (lock) {
            new Thread() {
                public void run() {
                    for (int i = 0; i < 100; i++) {                

        
                        printer.print2();
                    }
                }
            }.start();
        }
    }

}
class Printer{
    public static void print1() {
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
        System.out.println("4");
        System.out.println("\r\n");        
    }
    public static void print2() {
        System.out.println("A");
        System.out.println("B");
        System.out.println("C");
        System.out.println("D");
        System.out.println("\r\n");        
    }
}

 


同步方法:

public class Demo7_synchronized {
    //使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的

    public static void main(String[] args) {
//        Printer1 printer = new Printer1();
        Printer2 printer = new Printer2();
        new Thread() {
            public void run() {
                for (int i = 0; i < 100; i++) {                    

    
                    printer.print1();
                }
            }
        }.start();

        new Thread() {
            public void run() {
                for (int i = 0; i < 100; i++) {                    

    
                    printer.print2();
                }
            }
        }.start();

    }

}
class Printer1{
//    静态的同步函数的锁是:字节码对象
    public synchronized static void print1() {
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
        System.out.println("4");
        System.out.println("\r\n");    
    }
    public static void print2() {
        synchronized (Printer1.class) {
            System.out.println("A");
            System.out.println("B");
            System.out.println("C");
            System.out.println("D");
            System.out.println("\r\n");    
        }
    }
}

class Printer2{
//    非静态同步函数的锁是:this
    public synchronized void print1() {
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
        System.out.println("4");
        System.out.println("\r\n");    
    }
    public void print2() {
        synchronized (this) {
            System.out.println("A");
            System.out.println("B");
            System.out.println("C");
            System.out.println("D");
            System.out.println("\r\n");    
        }
    }
}


线程安全问题:

public class Test1 {

    public static void main(String[] args) {
        //多线程并发操作同一数据时, 就有可能出现线程安全问题
        //使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起

操作
//        new Ticket().start();
//        new Ticket().start();
//        new Ticket().start();
//        new Ticket().start();
        
        Ticket2 ticket2 = new Ticket2();
        new Thread(ticket2).start();
        new Thread(ticket2).start();
        new Thread(ticket2).start();
        new Thread(ticket2).start();
    }

}
class Ticket extends Thread{
    private static int ticket = 100;
//    private static Object object = new Object();
    public void run() {
        while(true) {
            synchronized (Ticket.class) {
                if (ticket<=0) {
                    break;
                }
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(getName() + ":这是第" + ticket-- + "张
");
            }
        }
        
    }
}

class Ticket2 implements Runnable{
    private static int ticket = 100;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true) {
            synchronized (this) {
                if (ticket<=0) {
                    break;
                }
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":这

是第" + ticket-- + "张票");
            }
        }
    }
    
}


多线程同步的时候, 如果同步代码嵌套, 使用相同锁, 就有可能出现死锁
 尽量不要嵌套使用

synchronized(s1) {
    System.out.println(getName());
    synchronized(s2) {
        System.out.println(getName());
    }
}

Vector,StringBuffer,Hashtable
Collections.synchroinzed(xxx)可以变成安全
    * Vector是线程安全的,ArrayList是线程不安全的
    * StringBuffer是线程安全的,StringBuilder是线程不安全的
    * Hashtable是线程安全的,HashMap是线程不安全的


单例设计模式:

public class Demo1_Singleton {

    public static void main(String[] args) {
        // 单例设计模式:保证类在内存中只有一个对象
        Singleton s1 = Singleton.getIntance();
        Singleton s2 = Singleton.getIntance();
        System.out.println(s1==s2); //true
    }

}
//饿汉式,空间换时间
class Singleton{
    private Singleton(){}
    private static Singleton s = new Singleton();
    public static Singleton getIntance() {
        return s;
    }
}
//懒汉式,单例的延时加载模式,存在多线程的问题,时间换空间
class Singleton1{
    private Singleton1(){}
    private static Singleton1 s;
    public static Singleton1 getIntance() {
        if (s==null) {
            s = new Singleton1();
        }
        return s;
    }
}

//final修饰
class Singleton2 {
    private Singleton2() {}
    public static final Singleton2 s = new Singleton2();//final修饰的变量不可以被更改
}



 Runtime类是一个单例类
        Runtime r = Runtime.getRuntime();
        //r.exec("shutdown -s -t 300");        //300秒后关机
        r.exec("shutdown -a");    


Timer:

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Demo2_Timer {

    public static void main(String[] args) throws Throwable {
        //Timer类:计时器
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行任务");
            }
        }, new Date(),3000);
        while(true) {
            Thread.sleep(1000);
            System.out.println(new Date());
        }
    }

}


两个线程间的通信:

public class Demo3_Notify {

    public static void main(String[] args) {
        //等待唤醒机制
//        如果希望线程等待, 就调用wait()
//        如果希望唤醒等待的线程, 就调用notify();
//        这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
        
        /*ABCD
        1234
        ABCD
        1234*/
        Printer printer = new Printer();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.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("A");
            System.out.print("B");
            System.out.print("C");
            System.out.print("D");
            System.out.print("\r\n");
            flag = 2;
            this.notify();
        }
    }
    public void print2() throws InterruptedException {
        synchronized (this) {
            if (flag!=2) {
                this.wait();
            }
            System.out.print("1");
            System.out.print("2");
            System.out.print("3");
            System.out.print("4");
            System.out.print("\r\n");
            flag = 1;
            this.notify();
        }
    }
}


多个线程通信:

public class Demo4_notifyall {

    public static void main(String[] args) {
        /*多个线程通信的问题
        * notify()方法是随机唤醒一个线程
        * notifyAll()方法是唤醒所有线程
        * JDK5之前无法唤醒指定的一个线程
        * 如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断

条件*/
        Printers printer = new Printers();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

}
class Printers{
    private int flag = 1;
    public void print1() throws InterruptedException {
        synchronized (this) {
            while (flag!=1) { //if语句是在哪里等待,就在哪里起来
                              //while循环是循环判断,每次都会判断标记
                this.wait();
            }
            System.out.print("A");
            System.out.print("B");
            System.out.print("C");
            System.out.print("D");
            System.out.print("\r\n");
            flag = 2;
            this.notifyAll();
        }
    }
    public void print2() throws InterruptedException {
        synchronized (this) {
            while (flag!=2) {
                this.wait();
            }
            System.out.print("1");
            System.out.print("2");
            System.out.print("3");
            System.out.print("4");
            System.out.print("\r\n");
            flag = 3;
            this.notifyAll();
        }
    }
    public void print3() throws InterruptedException {
        synchronized (this) {
            while (flag!=3) {
                this.wait();
            }
            System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.print("d");
            System.out.print("\r\n");
            flag = 1;
            this.notifyAll();
        }
    }
}


在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
 为什么wait方法和notify方法定义在Object这类中?
    因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在
Object这个类中
sleep方法和wait方法的区别?
 * sleep方法必须传入参数,参数就是时间,时间到了自动醒来wait方法可以传入参数也可以不传入参数,
传入参数就是在参数的时间结束后等待,不传入参数就是直接等待
 * sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡,wait方法在同步函数或者同步
代码块中,释放锁


ReentrantLock类:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Demo5_ReentrantLock {

    public static void main(String[] args) {
        /*JDK1.5的新特性互斥锁
           同步
        * 使用ReentrantLock类的lock()和unlock()方法进行同步
        通信
        * 使用ReentrantLock类的newCondition()方法可以获取Condition对象
        * 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法
        * 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了*/
        Printers1 printer = new Printers1();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        printer.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

}

class Printers1{
    private int flag = 1;
    private ReentrantLock r = new ReentrantLock();
    private Condition c1 = r.newCondition();
    private Condition c2 = r.newCondition();
    private Condition c3 = r.newCondition();
    public void print1() throws InterruptedException {
        r.lock();
            if (flag!=1) {
                c1.await();
            }
            System.out.print("A");
            System.out.print("B");
            System.out.print("C");
            System.out.print("D");
            System.out.print("\r\n");
            flag = 2;
            c2.signal();
        r.unlock();
    }
    public void print2() throws InterruptedException {
        r.lock();
            if (flag!=2) {
                c2.await();
            }
            System.out.print("1");
            System.out.print("2");
            System.out.print("3");
            System.out.print("4");
            System.out.print("\r\n");
            flag = 3;
            c3.signal();
        r.unlock();
    }
    public void print3() throws InterruptedException {
        r.lock();
            if (flag!=3) {
                c3.await();
            }
            System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.print("d");
            System.out.print("\r\n");
            flag = 1;
            c1.signal();
        r.unlock();
    }
}


线程组:

public class Demo6_ThreadGroup {

    public static void main(String[] args) {
        /*Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许

程序直接对线程组进行控制。
        * 默认情况下,所有的线程都属于主线程组。
            * public final ThreadGroup getThreadGroup()//通过线程对象获取他所属

于的组
            * public final String getName()//通过线程组对象获取他组的名字
        * 可以给线程设置分组
            * 1,ThreadGroup(String name) 创建线程组对象并给其赋值名字
            * 2,创建线程对象
            * 3,Thread(ThreadGroup?group, Runnable?target, String?name)
            * 4,设置整组的优先级或者守护线程*/
        MyRunnable1 mr = new MyRunnable1();
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        
        //线程组的使用,默认是主线程组
        System.out.println(t1.getThreadGroup().getName()); //main
        System.out.println(t2.getThreadGroup().getName()); //main
        
//        自己设定线程组
        ThreadGroup threadGroup = new ThreadGroup("自己设定线程组");
        MyRunnable1 mr2 = new MyRunnable1();
        System.out.println(new Thread(threadGroup, mr2).getThreadGroup().getName

()); //自己设定线程组
        System.out.println(new Thread(threadGroup, mr2).getThreadGroup().getName

()); //自己设定线程组
        
        

    }

}
class MyRunnable1 implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        
    }
    
}

 



线程池概述
    程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可
以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。线程池
里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使
用。在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池


内置线程池的使用概述
    JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
        * public static ExecutorService newFixedThreadPool(int nThreads)
        * public static ExecutorService newSingleThreadExecutor()
        * 这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行

Runnable对象或者Callable对象代表的线程。它提供了如下方法
        * Future<?> submit(Runnable task)
        * <T> Future<T> submit(Callable<T> task)
    * 使用步骤:
        * 创建线程池对象
        * 创建Runnable实例
        * 提交Runnable实例
        * 关闭线程池
    *
        * 提交的是Runnable
*
        ExecutorService pool = Executors.newFixedThreadPool(2);

        // 可以执行Runnable对象或者Callable对象代表的线程
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());

        //结束线程池
        pool.shutdown();



多线程程序实现的方式3(了解)
* 提交的是Callable
        * 好处:
        * 可以有返回值
        * 可以抛出异常
        
        * 弊端:
        * 代码比较复杂,所以一般不用
*
      

 // 创建线程池对象
        ExecutorService pool = Executors.newFixedThreadPool(2);

        // 可以执行Runnable对象或者Callable对象代表的线程
        Future<Integer> f1 = pool.submit(new MyCallable(100));
        Future<Integer> f2 = pool.submit(new MyCallable(200));

        // V get()
        Integer i1 = f1.get();
        Integer i2 = f2.get();

        System.out.println(i1);
        System.out.println(i2);

        // 结束
        pool.shutdown();

        public class MyCallable implements Callable<Integer> {

            private int number;
        
            public MyCallable(int number) {
                this.number = number;
            }
        
            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int x = 1; x <= number; x++) {
                    sum += x;
                }
                return sum;
            }
        
        }

 

简单工厂模式概述和使用
简单工厂模式概述
    又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
客户端不需要在负责对象的创建,从而明确了各个类的职责
这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不
断的修改工厂类,不利于后期的维护
示例:
    * 动物抽象类:public abstract Animal { public abstract void eat(); }
    * 具体狗类:public class Dog extends Animal {}
    * 具体猫类:public class Cat extends Animal {}
    * 开始,在测试类中每个具体的内容自己创建对象,但是,创建对象的工作如果比较麻烦,就

需要有人专门做这个事情,所以就知道了一个专门的类来创建对象。

  public class AnimalFactory {
            private AnimalFactory(){}
        
            //public static Dog createDog() {return new Dog();}
            //public static Cat createCat() {return new Cat();}
        
            //改进
            public static Animal createAnimal(String animalName) {
                if(“dog”.equals(animalName)) {return new Dog();}
                else if(“cat”.equals(animale)) {
                    return new Cat();
                }else {
                    return null;
                }
            }
        }


工厂方法模式概述:
工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实
现。
*  客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只需要增加一个
具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
*  需要额外的编写代码,增加了工作量
* 示例
*
        动物抽象类:public abstract Animal { public abstract void eat(); }
        工厂接口:public interface Factory {public abstract Animal createAnimal();}
        具体狗类:public class Dog extends Animal {}
        具体猫类:public class Cat extends Animal {}
        开始,在测试类中每个具体的内容自己创建对象,但是,创建对象的工作如果比较麻
烦,就需要有人专门做这个事情,所以就知道了一个专门的类来创建对象。发现每次修改代码太麻烦,
用工厂方法改进,针对每一个具体的实现提供一个具体工厂。
        狗工厂:public class DogFactory implements Factory {
            public Animal createAnimal() {…}
                }
        猫工厂:public class CatFactory implements Factory {
            public Animal createAnimal() {…}
                }  

GUI:

Frame  f = new Frame(“my window”);
        f.setLayout(new FlowLayout());//设置布局管理器
        f.setSize(500,400);//设置窗体大小
        f.setLocation(300,200);//设置窗体出现在屏幕的位置
        Button button = new Button("按钮1");
        f.add(button);
        f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));//设置图
标,默认是咖啡
        f.setVisible(true);


布局管理器:
* FlowLayout(流式布局管理器)
    * 从左到右的顺序排列。
    * Panel默认的布局管理器。
* BorderLayout(边界布局管理器)
    * 东,南,西,北,中
    * Frame默认的布局管理器。
* GridLayout(网格布局管理器)
    * 规则的矩阵
* CardLayout(卡片布局管理器)
    * 选项卡
* GridBagLayout(网格包布局管理器)
    * 非规则的矩阵

import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Demo1_Frame {

    public static void main(String[] args) {
        Frame frame = new Frame("my window");
        frame.setLayout(new FlowLayout());;//设置窗体大小
        frame.setSize(500,400);//设置窗体大小
        frame.setLocation(300,200);//设置窗体出现在屏幕的位置
        frame.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));//

置图标,默认是咖啡
        Button button = new Button("按钮1");
        Button button1 = new Button("按钮2");
        frame.add(button);
        frame.add(button1);
        button.addMouseListener(new MouseAdapter() {
            /*@Override
            public void mouseClicked(MouseEvent e) {
                //点击
                System.exit(0);
            }*/
            @Override
            public void mouseReleased(MouseEvent e) {
                //释放
                System.exit(0);
            }
        });
        button.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                System.out.println(e.getKeyCode());
//                if (e.getKeyCode()==32) { //空格
                if (e.getKeyCode()==KeyEvent.VK_SPACE) { //空格
                    System.exit(0);
                }
            }
        });
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        //动作监听
        button1.addActionListener(new ActionListener() {
        
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
                
            }
        });
        frame.setVisible(true);
    }

}
View Code


事件处理
    * 事件: 用户的一个操作
    * 事件源: 被操作的组件
    * 监听器: 一个自定义类的对象, 实现了监听器接口, 包含事件处理方法,把监听器添加在事件
源上, 当事件发生的时候虚拟机就会自动调用监听器中的事件处理方法

适配器设计模式:
* .什么是适配器
    * 在使用监听器的时候, 需要定义一个类事件监听器接口.
    * 通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐.
    * 适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需要的方法即可.
* .适配器原理
    * 适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的.
    * 适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的
    * 目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要的方法就可以了.

public class test1 {
//    适配器设计模式
}
interface Inter{
    public void A();
    public void B();
    public void C();
    public void D();
}

abstract class InterAdapter implements Inter{

    @Override
    public void A() {

    }

    @Override
    public void B() {

    }

    @Override
    public void C() {

    }

    @Override
    public void D() {

    }
    
}

class MyInter extends InterAdapter{
    @Override
    public void A() {
        
    }
}

 


总结:
1、单例设计模式,适配器设计模式
    单例设计模式:    
        在java中,单例模式是指为了保证类在内存中只有一个对象,而形成的一种固有的代
码模式
    适配器设计模式:
        在java中,适配器设计模式是指为了监视某些行为,但是对于每种监听到的行为又有
不同的处理,为了能够让监听者自行来处理监听到指定行为后,要做的后续操作,而形成的一种固有的
代码模式
        * a.什么是适配器
            * 在使用监听器的时候, 需要定义一个类事件监听器接口.
            * 通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写,
这很繁琐.
            * 适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需
要的方法即可.
        * b.适配器原理
            * 适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方
法全是空的.
            * 适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的
            * 目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要
的方法就可以了.
2、饿汉式和懒汉式的区别
    使用场合:
        饿汉式:    开发用
        懒汉式:    面使用,开发一般不用
    思想:
        饿汉式:    类一加载就生成对象。
        懒汉式:    在调用获取对象的方法的时候生成。
    实用性:
        饿汉式:    安全,效率高。相对懒汉式会在未使用之前就占用内存。
        懒汉式:    存在线程安全漏洞,可以利用同步解决,但是效率会变低。内存方面符合了
编程中的延迟加载思想。(在面试中面试官会比较希望答出这一点)
3、Timer类
    Timer类是计时器。
    一般的使用过程是在Timer类的schedule()方法中传入两个参数,一个TimerTask的子类对象,
在这个子类对象中规定了计时结束的操作,另一个java.util.Date类的对象,其参数指定了计时的开始时
间和循环周期,
4、wait和sleep的区别
    sleep方法:定义在Thread类中,让线程在指定时间内处于休眠状态,超时后继续向下执行,休
眠的线程不会释放锁资源。
    wait方法 :定义在Object类中,让以当前对象为监视器的线程处于阻塞状态,不可获取执行权
,在得到notify或者notifyAll的通知后再继续抢夺执行权。等待的线程会释放锁资源。
5、线程的生命周期(五中状态的切换流程)
    线程分为5个生命周期,新建,就绪,运行,阻塞,死亡
    其中:
        新建代表线程在内存中创建,对应start方法。
        就绪代表线程拥有抢夺执行权的资格,如果抢到就会执行线程中的内容
        运行代码线程中的内容正在执行。
            a:若被抢走执行权,回到就绪状态
            b:若执行ssleep、wait等方法,会进入阻塞状态。
        阻塞代表线程被强制不可进入就绪状态,对于非就绪状态的线程是没有机会抢夺执行
权,也就更不可能进入运行状态了。
        死亡代表线程运行结束,也可能是被强制结束,一般不建议使用。

posted @ 2018-11-02 10:11  fly_bk  阅读(500)  评论(0)    收藏  举报