线程学习(2)-Java基础学习总结

1.线程间的等待唤醒机制

相关方法介绍:

  • Wait()方法//等待 ,一但是等待状态就要释放锁 ,重哪里等待,便从哪里唤醒
  • notify()方法//唤醒一个等待线程,两线程依然竞争优先权
  • notifyAll()方法//唤醒所有等待线程,两线程依然竞争优先权
代码演示
生产资源类:
public class Increase extends Thread {
    student student;
    int i=0;
    public Increase(student student ) {
        this.student=student;
    }
    @Override
    public void run() {
        while(true){
            synchronized (student){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(student.flag){ //当资源存在时,进入等待时间
                    try {
                        student.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if(i%2==0){
                    student.name="张三";
                    student.age=18;
                }else{
                    student.name="李四";
                    student.age=25;
                }
                i++;
                student.flag=true;//更改标记状态
                student.notify();//唤起线程
            }
        }
    }
}
消费资源类
public class Decrease extends Thread {
    student student;

    public Decrease(student student) {
        this.student = student;
    }

    @Override
    public void run() {
        while(true){
            synchronized (student){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(!student.flag){
                    try {
                        student.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(student.name+"==="+student.age);
                student.flag=false;
                student.notify();
            }

        }
    }
}
变量类
public class student {
    public static String name;
    public static int age;
    public static boolean flag =false;//标记,用来表示资源是否存在,false无、true有
}

2.volatile关键字

volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
解释: 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值,避免了多线程因不能及时更新内存,导致数据错乱问题;
volatile 变量,用来确保将变量的更新操作通知到其他线程。

  • 对于多线程,不是一种互斥关系
  • 但不能保证变量状态的“原子性操作”
CAS算法:比较并交换
内存值与自己的预估值进行比较,若相等对内存值进行修改;不相等,就不进行任何操作(把普通变量换成原子变量AtomicInteger I = new AtomicInteger(1),调用getAndIncrement()方法进行自加)
CAS算法比Synchronized效率高

3. 线程池

原有一次创建一个线程,当需要多个线程时,就会大大的不方便,而使用线程池可以很好的提高性能,线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。JDK5可以使用Executors工厂类来产生线程池;
方法介绍:

  • newCachedThreadPool(): //根据任务的数量来创建线程对应的线程个数
  • newFixedThreadPool(int nThreads): //固定初始化几个线程
  • newSingleThreadExecutor(): //初始化一个线程的线程池
    对应提供了如下增加任务方法:
  • Future submit(Runnable task)
  • Future submit(Callable task)
代码演示
public class test {
    public static void main(String[] args) {
        ExecutorService t = Executors.newCachedThreadPool();//更具任务个数
        ExecutorService t1 = Executors.newFixedThreadPool(2);//固定2个xiancheng
        ExecutorService t2 = Executors.newSingleThreadExecutor();//当个线程
        t.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"我好困呀!!");
            }
        });
        t1.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"眼睛花了!!");
            }
        });
        t1.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"汗水哗啦啦!!");
            }
        });
        t2.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"夏天的西安真热!!");
            }
        });
        t.shutdown();
        t1.shutdown();
        t2.shutdown();
    }
}

4.定时器

定时器概述:定时器是一个应用十分广泛的线程工具,可用于调度多个定时任务以后台线程的方式执行。
可以通过Timer和TimerTask类来实现定义调度的功能。
Timer和TimerTask
Timer方法:
public Timer()
public void schedule(TimerTask task, long delay);
public void schedule(TimerTask task,long delay,long period);
public void schedule(TimerTask task, Date time):
public void schedule(TimerTask task, Date firstTime, long period):
TimerTask方法:定时任务
public abstract void run()
public boolean cancel() //关闭定时器

代码演示:
public class test {
    public static void main(String[] args) throws ParseException {
        Timer timer = new Timer();
     
        timer.schedule(new TimerTask() {//在2019-7-31 21:24:00时,执行任务
            @Override
            public void run() {
                System.out.println("我再练习啦啦。");
            }
        },new SimpleDateFormat("yyyy-mm-dd hh:mm:ss").parse("2019-7-31 21:24:00"));
        timer.schedule(new TimerTask() {//运行后一秒执行
            @Override
            public void run() {
                System.out.println("我再练习哈哈。");
            }
        },1000);
        timer.schedule(new TimerTask() {//运行后一秒执行,然后每隔一秒执行一次
            @Override
            public void run() {
                System.out.println("我再练习哈哈。吼吼");
            }
        },1000,1000);
       
    }
}

Sleep()与wait()方法的区别
共同点:使线程,处于阻塞状态
Sleep必须设置时间  wait()可以不设置时间
Sleep方法:线程阻塞后,不释放锁
Wait方法:线程阻塞后,释放锁

设计模式(单例模式)

单例模式:一个类只能有一个对象;

懒汉式:
对象类实现
public class student {
    private static student stu =null;
    public static student getStu(){
        if(stu==null){
            stu= new student();
        }
        return stu;
    }
}
测试类实现:
public class test {
    public static void main(String[] args) {
        student stu = student.getStu();
        student stu1 = student.getStu();
        System.out.println(stu==stu1);
    }
}
饿汉式:
public class student1 {
    private static student1 stu= new student1 ();
    public static student1  getStu(){
        return stu;
    }
}
测试类实现:
public class test1 {
    public static void main(String[] args) {
        student1  stu = student1.getStu();
        student1 stu1 = student1.getStu();
        System.out.println(stu==stu1);
    }
}

Runtime类:单例模式的应用

 每个Java应用程序都有一个Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。  

特有方法:public Process exec(String command) //执行Dos 命令

代码实现:
public class test3 {
    public static void main(String[] args) throws IOException {
        Runtime runtime = Runtime.getRuntime();
       runtime.exec("calc");//打开电脑计算器
    }
}

你可能感兴趣的:(线程学习(2)-Java基础学习总结)