Java多线程(下)

Java多线程(下)

单例设计模式

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

饿汉式

public class Demo_Singleton {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
    }
}

class Singleton{
    //私有构造方法
    private Singleton(){}
    //创建本类对象
    private static Singleton s = new Singleton();

    public static Singleton getInstance(){
        return s;
    }
}

懒汉式

public class Demo_Singleton {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
    }
}
class Singleton{
    //私有构造方法
    private Singleton(){}
    //声明引用
    private static Singleton s;

    public static Singleton getInstance(){
        if(s==null)
            s=new Singleton();
        return s;
    }
}

这种方式,在多线程中可能会出现创建了多个对象。

第三种方式

public class Demo_Singleton {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
    }
}

class Singleton{
    //私有构造方法
    private Singleton(){}
    //创建本类对象
    public static final Singleton s = new Singleton();
}

Runtime类(单例设计模式应用)

import java.io.IOException;

public class Demo_Runtime {
    public static void main(String[] args) throws IOException {
        Runtime r = Runtime.getRuntime();
        r.exec("shutdown - s -t 300");
    }
}

在这里插入图片描述

Timer(计时器)

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

public class Demo_Timer {
    public static void main(String[] args) {
        Timer t = new Timer();
        t.schedule(new MyTimerTask(),new Date(119,6,30,11,5,30));//在指定时间安排指定任务
        /*
         * 第一个参数是安排的任务,第二个参数是执行的时间,若有第三个参数则是过多长时间重复执行
         * new Date(year,month,date,hrs,min,sec)
         * year - 减1900的年份
         * month - 0-11之间的月份
         * date - 一月中1-31的某一天
         * hrs - 0-23之间的小时
         * min - 0-59的分钟
         * sec - 0-59的秒
         */
    }
}

class MyTimerTask extends TimerTask{
    @Override
    public void run() {
        System.out.println("起床背单词!!");
    }
}

线程间的通信注意的问题

  • 在同步代码块中,用哪个对象锁,就用哪个对象调用wait()方法

  • 为什么wait()和notify()方法定义在Object这类中?

    因为锁对象可以是任意对象,Object是所有类的基类

  • sleep()和wait()方法的区别

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

      wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间过了之后等待,不传入参数就是立即等待

    • sleep方法在同步方法或同步代码块中不释放锁

      wait方法在同步方法或同步代码块中释放锁

互斥锁

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

使用Condition的await()和signal()方法来使线程等待或唤醒,与notify()方法不同的是signal()可以唤醒指定线程

public class Demo_Thread {
    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();
        new Thread(){
            public void run(){
                while(true){
                    try {
                        p.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

    }
}

class Printer {
    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("安");
        System.out.print("卓");
        System.out.print("开");
        System.out.print("发");
        System.out.println();
        flag = 2;
        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("工");
        System.out.print("程");
        System.out.print("师");
        System.out.println();
        flag = 3;
        c3.signal();
        r.unlock();
    }

    public void print3() throws InterruptedException{
        r.lock();
        if(flag != 3){
            c3.await();
        }
        System.out.print("后");
        System.out.print("台");
        System.out.print("程");
        System.out.print("序");
        System.out.print("员");
        System.out.println();
        flag = 1;
        c1.signal();
        r.unlock();
    }
}
//输出:
前端工程师
后台程序员
安卓开发
前端工程师
后台程序员
安卓开发
前端工程师
后台程序员
安卓开发
前端工程师
后台程序员

线程组的概述和使用

概述

Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。

默认是主线程

public class Demo_ThreadGroup {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(mr,"张三");
        Thread t2 = new Thread(mr,"李四");

        ThreadGroup tg1 = t1.getThreadGroup();
        ThreadGroup tg2 = t2.getThreadGroup();
        System.out.println(tg1.getName());
        System.out.println(tg2.getName());
    }
}

class MyRunnable implements Runnable{
    public void run(){
        for (int i = 0;i<1000;i++){
            System.out.println(Thread.currentThread().getName()+"..."+i);
        }
    }
}
//输出:main
	   main

创建线程组

通过Thread的构造方法将线程添加进线程组

线程的五种状态

在这里插入图片描述

线程池

1.概述

程序启动一个新线程的成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存周期很短的线程时,更应该考虑线程池。线程池里面的每一个线程代码结束后并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

ExecutorsService pool = Executors.newFixedThreadPool(n);//n是线程池中的线程数量

pool.submit();//向线程池中添加线程并执行

pool.shutdown();//关闭线程池
发布了31 篇原创文章 · 获赞 9 · 访问量 1616

猜你喜欢

转载自blog.csdn.net/qq_43621019/article/details/98241684
今日推荐