美文网首页
Java基础笔记总结(17)-线程 单例模式 线程池 工厂模式

Java基础笔记总结(17)-线程 单例模式 线程池 工厂模式

作者: 吵吵先生 | 来源:发表于2019-01-31 17:29 被阅读0次

    线程:

    线程是程序的执行路径,一个进程包含多条线程

    多线程的并发执行可以提高程序的效率,可以同时完成多项工作。

    多行程并行和并发的区别

    并行的使用 要使用多核CPU

    并发指两个任务都运行,而处理器只能接受一个任务,将两个任务轮流执行

    Java命令启动java虚拟机,启动JVM等于启动一个进程,该进程会自动启动一个“主线程”,然后主线程去调用某类的main方法

    JVM的启动至少启动了垃圾回收线程和主线程,因此JVM是多线程的,注意线程是穿插执行

    多线程

    1、继承Thread,并且重写Thread的run方法,并分配和启动该子类的实例

    public static void main(String[] args) {

    MyThread mt = new MyThread();

    mt.start();

    for (int i = 0; i < 1000; i++) {

    System.out.println("xxxxxxx");

    }

    }

    }

    class MyThread extends Thread{

    @Override

    public void run() {

    for (int i = 0; i < 1000; i++) {

    System.out.println("测试"+i);

    }

    }

    2、实现Runnable()接口

    new Thread(new Runnable() {

    @Override

    public void run() {

    // TODO Auto-generated method stub

    }

    }).start();

    -------------------------------------------------------------------------

    Runnable和Thread的区别

    a 继承Thread 由于子类重写了Thread类的run(),调用start()时,直接调用子类的run方法 实现代码简单,但是如果有父类,不能实现Thread。

    b 实现Runnable 构造函数中传入Runnable的引用,成员变量通过记住它,start()调用run(方法)判断是否引用为空,如果不为空,编译Runnable的run(),运行时执行子类的run()方法,实现代码复杂,需要先获取到线程对象,才能使用Thread的方法

    -------------------------------------------------------------------------

    采用匿名内部类实现两种方法

    new Thread(

    public void run(){

    }

    ).start();

    new Thread(new Runnable(){

    public void run(){

      }

    }).start();

    --------------------------------------------------------------------

    获取

    getName() 获取线程名称

    new Thread(new Runnable() {

    @Override

    public void run() {

      this.getName();

    }

    }).start();

    setName()可以改变名称或者在构造方法中修改名称

    --------------------------------------------------------------------

    获取当前线程的对象

    Thread t = Thread.CurrentThread();

    要使用Runnable接口,可以使用Thread.CurrentThread()获取当前线程;

    -------------------------------------------------------------------

    线程休眠

    Thread.sleep(毫秒,纳秒);

    -------------------------------------------------------------------

    setDemon 守护线程

    设置一个线程为守护线程,该线程不会单独执行,当其他非守护线程都执行结束后,自动退出

    当非守护线程都执行结束后,自动退出

    --------------------------------------------------------------------

    加入线程

    join()当前线程暂停,等待指定的线程执行结束后,当加入线程结束后,在继续执行线程

    匿名内部类使用局部变量时候,必须用final修饰

    使用局部变量

    ---------------------------------------------------------------------

    礼让线程 yield()

    ---------------------------------------------------------------------

    设置线程优先级

    norm = 5

    min = 1

    max = 10

    new Thread().setPriority(Thread.MIN_PRIORITY);

    ---------------------------------------------------------------------

    同步代码块

    当多段代码同时执行的过程中,我们希望cpu不要切换到其他线程工作,就需要同步操作

    synchronized 同步代码块

    锁对象是任意的,但是不能使用匿名内部类,因为匿名对象不是同一个对象

    public static void main(String[] args) {

    new Thread(){

    public void run() {

    Test t = new Test();

    t.print1();

    };

    }.start();

    new Thread(){

    public void run() {

    Test t = new Test();

    t.print2();

    };

    }.start();

    }

    }

    class Test {

    static Lock lock = new Lock();

    public static void print1(){

    synchronized(lock){

    System.out.println("xxxxxxx");

    }

    }

    public static void print2(){

    synchronized(lock){

    System.out.println("yyyyyyyyy");

    }

    }

    }

    class  Lock{

    public Lock(){

    }

    }

    --------------------------------------------------------------------------

    如果同步方法,在方法上加synchronized关键字即可

    非静态的同步方法的锁对象是this

    静态方法的同步方法锁对象是 Object.class 该类的字节码文件

    ------------------------------------------------------------------------

    线程安全问题

    铁路售票问题  共有100张,通过4个窗口买完

    如果引用数据类型成员变量当成锁对象,要加静态类型

    public class Demo_Ticket {

    public static void main(String[] args) {

    new Ticket().start();

    new Ticket().start();

    new Ticket().start();

    new Ticket().start();

    }

    }

    class Ticket extends Thread {

    private static int ticket = 100;

    @Override

    public void run() {

    while (true) {

    synchronized (Ticket.class) {

    if (ticket <= 0) {

    break;

    }

    try {

    Thread.sleep(10);

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    System.out.println(getName() + "....第" + ticket-- + "张");

    }

    }

    }

    }

    ---------------------------------------------------------------------------

    Runnable接口实现

    ---------------------------------------------------------------------------

    哲学家筷子问题 (不要出现同步代码块嵌套)

    public class Demo_Lock {

    private static String s1 = "筷子左";

    private static String s2 = "筷子右";

    public static void main(String[] args) {

    new Thread (new Runnable() {

    public void run() {

    while (true) {

    synchronized(s1){

    System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

    synchronized(s2){

    System.out.println("拿到"+s2+"开吃");

    }

    }

    }

    }

    }).start();

    new Thread (new Runnable() {

    public void run() {

    while (true) {

    synchronized(s1){

    System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

    synchronized(s2){

    System.out.println("拿到"+s2+"开吃");

    }

    }

    }

    }

    }).start();

    new Thread (new Runnable() {

    public void run() {

    while (true) {

    synchronized(s1){

    System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

    synchronized(s2){

    System.out.println("拿到"+s2+"开吃");

    }

    }

    }

    }

    }).start();

    new Thread (new Runnable() {

    public void run() {

    while (true) {

    synchronized(s1){

    System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

    synchronized(s2){

    System.out.println("拿到"+s2+"开吃");

    }

    }

    }

    }

    }).start();

    }

    }

    Vector是线程安全的

    ArrayList 是线程不安全的

    StringBuffer 是线程安全的

    StringBuilder 是线程不安全的

    HashTable是线程安全的 HashMap是线程不安全的

    将不安全的线程变成安全的 用类Collections

    单例设计模式

    public class Demo_SIngleton {

    // 保证内存中只有一个对象

    public static void main(String[] args) {

    // Singleton s1 = new Singleton();

    /*Singleton s1 = Singleton.s;

    Singleton s2 =Singleton.s;

    System.out.println(s1==s2);*/

    Singleton s1 = Singleton.getInstance();

    Singleton s2 = Singleton.getInstance();

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

    }

    }

    // 饿汉式 直接创建对象比较好  空间换时间 不会创建多个对象

    class Singleton{

    // 私有构造,其他类不能访问该构造方法

    private Singleton(){}

    // 创建本类对象 成员变量私有,不能调用

    private static Singleton s = new Singleton();

    // 对外提供公共的访问方法

    public static Singleton getInstance(){

    return s;

    }

    }

    //懒汉式  会出现多线程的问题 时间换空间 有可能创建多个对象

    class Singleton2{

    // 私有构造,其他类不能访问该构造方法

    private Singleton2(){}

    // 创建本类对象 成员变量私有,不能调用

    private static Singleton2 s ;

    // 对外提供公共的访问方法

    public static Singleton2 getInstance(){

    if (s == null){

    s = new Singleton2();

    }

    return s;

    }

    }

    //

    class Singleton3{

    // 私有构造,其他类不能访问该构造方法

    private Singleton3(){}

    // 创建本类对象 成员变量私有,不能调用

    private static final Singleton3 s = new Singleton3();;

    // 对外提供公共的访问方法

    public static Singleton3 getInstance(){

    return s;

    }

    }

    -----------------------------------------------------------------------------------

    Runtime类

    import java.io.IOException;

    public class Demo_Runtime {

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

    //获取运行时对象

    Runtime runTime = Runtime.getRuntime();

    //执行字符串命令

    //runTime.exec("shutdown -s -t 300");

    runTime.exec("shutdown -a");

    }

    }

    -------------------------------------------------------------------------------------

    Timer 类(参数1:安排的任务 参数2:执行的时间 参数3:过多久再执行一次)

    线程安排在后台执行任务,或者定期重复执行,指定时间安排指定任务

    public class Demo_Timer {

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

    Timer t = new Timer();

    t.schedule(new MyTimerTask(),new Date(108,0,31,10,48,0), 5000);

    while(true){

    Thread.sleep(1000);

    System.out.println(new Date());

    }

    }

    }

    class MyTimerTask extends TimerTask{

    @Override

    public void run() {

    System.out.println("起床");

    }

    }

    --------------------------------------------------------------------------------------

    两个线程的通信(交替执行)

    public class Demo_ThreadCommuicate {

    //等待唤醒机制 wait() notify()

    public static void main(String[] args) {

    final Printer p = new Printer();

    new Thread(){

    public void run(){

    while (true) {

    try {

    p.print1();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    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("A");

    System.out.print("B");

    System.out.print("\r\n");

    flag = 2;

    this.notify();

    }

    }

    public  void print2() throws InterruptedException {

    synchronized(this){

    if(flag!=2){

    this.wait();

    }

    System.out.print("Z");

    System.out.print("W");

    System.out.print("\r\n");

    flag = 1;

    this.notify();

    }

    }

    }

    -------------------------------------------------------------------------------

    三个或三个以上线程的通信 notify()是随即唤醒线程

    public class Demo_notifyAll {

    public static void main(String[] args) {

    final Printer2 printer2 = new Printer2();

    new Thread(){

    public void run() {

    while(true){

    try {

    printer2.print1();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    };}.start();

    new Thread(){

    public void run() {

    while(true){

    try {

    printer2.print2();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    };}.start();

    new Thread(){

    public void run() {

    while(true){

    try {

    printer2.print3();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    };}.start();

    }

    }

    class Printer2{

    private int flag = 1;

    public void print1() throws InterruptedException{

    synchronized(this){

    while(flag!=1){

    this.wait();

    }

    System.out.print("A");

    System.out.print("B");

    System.out.print("\r\n");

    flag = 2;

    this.notifyAll();

    }

    }

    public void print2() throws InterruptedException{

    synchronized(this){

    while (flag!=2){

    this.wait();

    }

    System.out.print("M");

    System.out.print("N");

    System.out.print("\r\n");

    flag = 3;

    this.notifyAll();

    }

    }

    public void print3() throws InterruptedException{

    synchronized(this){

    while(flag!=3){

    this.wait();

    }

    System.out.print("Z");

    System.out.print("W");

    System.out.print("\r\n");

    flag = 1;

    this.notifyAll();

    }

    }

    } }

    }

    注意事项:

    在同步中,用什么对象作锁,就用什么对象wait()和notify()

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

    Sleep和wait的区别

    sleep必须传入参数,参数就是时间,时间到,自动唤醒

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

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

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

    ------------------------------------------------------------------------------

    JDK1.5 互斥锁

    ReentrantLock类的lock() unlock()替换synchronized

    import java.util.concurrent.locks.Condition;

    import java.util.concurrent.locks.ReentrantLock;

    public class Demo_Lock {

    public static void main(String[] args) {

    final Printer3 p3 = new Printer3();

    new Thread(){

    public void run() {

    while(true){

    try {

    p3.print1();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    };}.start();

    new Thread(){

    public void run() {

    while(true){

    try {

    p3.print2();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    };}.start();

    new Thread(){

    public void run() {

    while(true){

    try {

    p3.print3();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    };}.start();

    }

    }

    class Printer3 {

    private ReentrantLock r = new ReentrantLock();

    private int flag = 1;

    private Condition c1 = r.newCondition();

    private Condition c2 = r.newCondition();

    private Condition c3 = r.newCondition();

    public void print1() throws InterruptedException {

    r.lock();

    while (flag != 1) {

    c1.await();

    }

    System.out.print("A");

    System.out.print("B");

    System.out.print("\r\n");

    flag = 2;

    c2.signal();

    r.unlock();

    }

    public void print2() throws InterruptedException {

    r.lock();

    while (flag != 2) {

    c2.await();

    }

    System.out.print("M");

    System.out.print("N");

    System.out.print("\r\n");

    flag = 3;

    c3.signal();

    r.unlock();

    }

    public void print3() throws InterruptedException {

    r.lock();

    while (flag != 3) {

    c3.await();

    }

    System.out.print("Z");

    System.out.print("W");

    System.out.print("\r\n");

    flag = 1;

    c1.signal();

    r.unlock();

    }

    }

    lock()上锁

    unlock()解锁

    Condition c = r.newCondition();

    c.await() == this.wait()

    c.singnal() == this.notifyAll()  可以指定线程而无需全部唤醒

    ----------------------------------------------------------------

    线程组的概述和使用

    TreadGroup 表示线程组,允许对一群线程组管理 Java允许其对线程组管理

    public class Demo_ThreadGroup {

    public static void main(String[] args) {

    MyRunnable myRunnable = new MyRunnable();

    Thread t1 = new Thread(myRunnable,"张三");

    Thread t2 = new Thread(myRunnable,"李四");

    ThreadGroup tg1 = t1.getThreadGroup();//默认是主线程

    System.out.println(tg1.getName());

    ThreadGroup tg2 = t2.getThreadGroup();//默认是主线程

    System.out.println(tg2.getName());

    //如何设置线程组

    ThreadGroup tg = new ThreadGroup("我是新的线程组");

    MyRunnable mr = new MyRunnable();

    Thread t3 = new Thread(tg,mr,"张三");

    Thread t4 = new Thread(tg,mr,"李四");

    Thread t5 = new Thread(tg,mr,"王五");

    System.out.println(t3.getThreadGroup().getName());

    tg.setDaemon(true);

    }

    }

    class MyRunnable implements Runnable{

    @Override

    public void run() {

    for (int i = 0; i < 1000; i++) {

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

    }

    }

    }

    ------------------------------------------------------------------

    线程的五种状态

    线程的生命周期:

    新建 创建线程对象

    就绪 想成对象已经启动,但未获得CPU执行权

    运行 获得CPU执行权

    阻塞 没有CPU执行权,回到就绪

    死亡 代码运行完毕,线程消亡

    -------------------------------------------------------------------

    线程池的概述和使用

    使用线程池能够很好提高性能,尤其当程序中创建大量生命周期较短的线程时,更要考虑线程池,线程池中的代码结束后,并不会死亡,而是返回线程池变成空闲状态,

    Java内置的线程池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实例

    提交Runnbale实例

    关闭线程池

    // 创建线程池

    ExecutorService pool = Executors.newFixedThreadPool(2);

    pool.submit(new MyRunnable());//将县城放入池中并并行

    pool.submit(new MyRunnable());

    pool.shutdown();//关闭线程池

    -----------------------------------------------------------------------------

    多线程(多线程程序实现的方式)

    提交的是Callable

    import java.util.Iterator;

    import java.util.concurrent.Callable;

    import java.util.concurrent.ExecutionException;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    import java.util.concurrent.Future;

    public class Demo_Callable {

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

    ExecutorService pool = Executors.newFixedThreadPool(2);

    Future<Integer> f1 =  pool.submit(new MyCallable(100));

    System.out.println(f1.get());

    Future<Integer> f2 =  pool.submit(new MyCallable(50));

    System.out.println(f2.get());

    pool.shutdown();

    }

    }

    class MyCallable implements Callable<Integer>{

    private int num ;

    public  MyCallable(int num) {

    this.num = num;

    }

    @Override

    public Integer call() throws Exception {

    int sum = 0;

    for (int i = 0; i <= num; i++) {

    sum+=i;

    }

    return sum;

    }

    }

    ------------------------------------------------------------------------------------------------

    简单工厂模式

    称为 静态工厂方法模式,定义一个具体工厂类来创建类的实例

    优点:客户端不需要在负责对象的创建,从而明确了各个类的职责

    缺点:该静态工厂负责所有类的创建,如果有对象增加,或者修改对象创建方式,就要不断的修改工厂类,不利于维护啊

    -------------------------------------------------------------------------------------------------

    工厂方法模式 (抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现)

    将工厂类抽取成接口,对不同的对象生成不同的工厂来生产产品

    public interface Factory {

    public Animal createAnimal();

    }

    public class DogFactory implements Factory {

    @Override

    public Animal createAnimal() {

    return new Dog();

    }

    }

    ----------------------------------------------------------------------------------------------------

    GUI界面显示

    Graphical User Interface

    Frame f = new Frame("xxxx");

    f.setLayout();

    f.setSize(400,600);

    f.setLocation(300,50);

    f.setIcomImage(Toolkit.getDefaultToolkit().createImage());

    FlowLayout 流式布局管理器

    BorderLayout 边界布局管理器

    GridLayout 网格布局管理器

    CardLayout 卡片布局管理器

    GridBagLayout 网格背包管理器

    f.setVisible(true);//设置窗体可见

    GUI布局管理器

    -----------------------------------------------------------------------------------------------------

    窗体的监听

    f.addWindowListener();  //windowAdapter 实现了WIndowListener,并且重写了空方法

    鼠标监听

    f.addMouseListener();  MouseAdapter重写部分方法

    键盘监听

    f.addKeyListener();      KeyAdapter()适配监听 Event.VK_Z

    动作监听

    button.addActionListener  执行actionPerFormed(ActionEvent e)//添加动作场景

    --------------------------------------------------------------------------------------------------------

    适配器设计模式

    定义一个类事件的监听器接口

    适配器简化了操作,定义监听器时候只要集成适配器,然后重写了需要的方法即可

    适配器类必须是抽象的

    适配器类重写方法,但是方法全部为空,但是实际上是你需要那个方法就重写哪个方法,起到了一个过渡的作用

    相关文章

      网友评论

          本文标题:Java基础笔记总结(17)-线程 单例模式 线程池 工厂模式

          本文链接:https://www.haomeiwen.com/subject/hfklsqtx.html