JavaEE基础篇————线程

JavaEE基础篇————线程

  • 线程与进程
  • 实现线程的三种方法
  • 线程生命周期
  • 线程的常用方法
  • 线程调度方法----了解
  • 线程安全——重点
  • 线程中其他内容

线程与进程

  1. 什么是线程,什么是进程

    进程:是一个应用程序
    线程:是一个进程的执行场景/执行单元
    
  2. 在java程序中,运行后会先启动JVM进程,而JVM会启用一个main方法和GC垃圾回收站这两个进程。

  3. 进程A与B内存不共享,线程A与线程B在Java语言中:堆内存与方法区内存共享,但栈内存是独立的,一个线程一个栈。

实现线程的三种方法

  1. 编写一个类,直接继承Thread,重写run()方法。
//方法一:继承Thread类
class MyThread1 extends Thread{
    @Override
    public void run(){
        for (int i=0;i<=100;i++){
            System.out.println("线程一,继承类Thread:"+i);
        }
    }
}
实例化(创建)线程: 
Thread t1 = new MyThread1();
        t1.start();
  1. 编写一个类,实现Runnable接口,在创建一个线程类时将这个类当作参数传进去
//实现Runable接口,并不是线程,只是一个可运行的对象
class MyThread2  implements Runnable{
    @Override
    public void run() {
        for (int i=0;i<=10;i++){
            System.out.println("线程二,实现接口Runnable:"+i);
        }
    }
}
实例化(创建)线程:
 MyThread2 mt = new MyThread2();
        Thread t2 = new Thread(mt);
        t2.start();
  1. 使用匿名内部类创建线程:
//方法一 继承Thread类
         new Thread(){
            @Override
            public void run(){
                    for(int i=0;i<100;i++){
                        System.out.println("方法一:"+i);
                    }
            }
        }.start();
        //方法二:实现Runnable接口
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("方法二:" + i);
                }
            }
    });
        thread.start();
  1. 实现Callable接口(JDK8后的新特性)
    run()执行后可以具有返回值
 //创建一个”未来任务类“对象
        FutureTask task = new FutureTask(new Callable(){

            @Override
            public Object call() throws Exception {
                return null;
            }
        });

线程生命周期

新建状态,就绪状态,运行状态,阻塞状态,死亡状态
JavaEE基础篇————线程_第1张图片

线程的常用方法

    1,怎么获取线程对象     currentThread();         start Thread静态方法
                        出现在那就是那个线程
    2,获取线程名字        getName();
    3,修改线程名字        setName();
    4,当线程没有设置名字是,默认名称:
        Thread——0;
        Thread——1;
        Thread——2;
            ......
        5,线程的sleep方法    sleep();
                静态方法,参数是毫秒,作用是让当前线程进入休眠状态
                Thread.sleep();   方法间隔特定的事件去执行一段特定的代码,阻塞当前线程
                注意:在哪那个线程休眠,与前面引用的对象无关
        6.唤醒休眠线程     interrupter();    靠的是java异常机制
        7,强行终止一个线程  stop();(已过时)           直接终止一个线程,容易丢失数据
        8,合理的终止      在run里面加一个if语句进行修改falsetrue

```java
 public static void main(String[] args) {
        //获取当前线程对象(出现在main方法中,就是main线程)
        Thread currentThread =Thread.currentThread();
        System.out.println(currentThread.getName());

        //创建线程对象
        Mythread02 t = new Mythread02();
        //设置线程名字
        t.setName("ttttt");
        //线程休眠
        try {
            //一下三行代码的作用都是一样让主线main程休眠
            t.sleep(5000);
            currentThread.sleep(2000);
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //获取线程名字
        String s = t.getName();
        System.out.println(s);
        t.start();
        t.interrupt();
    }

class Mythread02 extends Thread{
    @Override
    public void run(){
        for (int i=0;i<=100;i++){
            try {
                //特定时间执行
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程一,继承类Thread:"+i);
        }
    }
}

线程调度方法----了解

 /*    线程调度:
        1,实例方法:
               void setPriority(int newPriority)    更改此线程的优先级。
               int getPriority()                    返回此线程的优先级。
               最低为1,最高为10
               优先级高获得的时间片可能更多
        2,静态方法   yield()                         让位方法,暂停当前执行的线程状态,不是阻塞方法
        3,实例方法   join()                          合并线程
*/
 System.out.println("最高优先级"+Thread.MAX_PRIORITY);
        System.out.println("最低优先级"+Thread.MIN_PRIORITY);
        System.out.println("默认优先级"+Thread.NORM_PRIORITY);

        //获取当前线程优先级
        Thread currentThread = Thread.currentThread();
        System.out.println(currentThread.getPriority());

        //设置主线程优先级
        Thread.currentThread().setPriority(1);
        Thread t = new Mythread03();
        t.setPriority(10);
        t.start();

        for(int i =0;i<1000;i++){
            System.out.println("---->"+i);
        }

线程安全——重点

  1. 什么时候数据在多线程并发的环境下会存在安全问题呢?
    三个条件:
    条件一:多线程并发
    条件二:有共享数据
    条件是:有共享数据的修改
  2. 怎么解决线程安全问题呢?
    线程排队执行(不能并发)
    用排队执行来解决这种问题,会牺牲一些效率。
    该机制称为:“线程同步机制”
  3. 异步编程模型与同步编程模型
    异步编程模型:多线程并发(效率较高)
    同步编程模型:线程排队执行(效率较高)
  4. 同步代码块synchronize
    synchronize(①){②}
    ①中填线程共享对象,例如:填this(此处需要去理解)
    ②中填需要排队执行的代码块
  5. synchronize的三种使用方法
    一:synchronize同步代码块
    二:在实例方法是加synchronize关键字(所指向的对象一定是this,可能导致执行效率低,也可能扩大同步范围)
    三:在静态方法中使用
    对象锁:保证成员变量安全
    类锁:保证静态变量安全,synchronize出现在静态方法中。
    6.死锁现象
    synchronize在程序中最好不要嵌套使用

线程中其他内容

1.守护线程
java语言线程分为两类:用户线程和守护线程(后台线程)
守护线程的特点:一般守护线程是一个死循环, 所有用户线程结束守护线程就结束。比如:垃圾回收线程GC

public class ThreadSHXC {
    public static void main(String[] args) {
        Thread t = new BakDateThread();
        t.setName("数据备份");
        t.setDaemon(true);
        t.start();

        //主线程
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+"--->"+(++i));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        }
    }
//数据备份
class BakDateThread extends Thread{
     public void run(){
         int i =0;
         while(true){//即使是死循环,也会自动退出
             System.out.println(Thread.currentThread().getName()+"--->"+(++i));
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
     }
}

2,定时器

定时器的作用:
   间隔特定的时间,并执行特定的程序。

   在java,util.Timer,可以直接拿来用。(不过后期许多框架都支持定时任务)	
 //创建定时器对象
        Timer time = new Timer();

        //指定定时任务
        //time.schedule(定时任务,执行时间,间隔多久);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date fristTime = sdf.parse("2020-09-27 18:10:00");
        time.schedule(new LogTimeTask(),fristTime,1000*3);

        //匿名内部类方式
        time.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("匿名内部类");
            }
        },fristTime,1000*3);
    }

3,关于object类中的wait和notify方法(生产和消费者模式)
wait和notify方法不是线程对象特有的方法,是java中任何一个java对象都有的方法,Object类自带的
wait:
Object o = new Object();
o.wait();
表示:让正在o对象上的线程进入等待状态,无期限等待,直到被唤醒
notify:
Object o = new Object();
o.notify();唤醒等待
生产者和消费者模式:

/*
生产者和消费者模式:使用wait与notify方法
    1,什么是生产者和消费者模式?
       生产线程负责生产,消费线程负责消费,两者达到平衡
    2,两个方法建立在线程同步的基础之上
    3,o.wait方法的作用:让线程进入等待状态,释放对象锁
    4,o.notify()让正在等待的对象唤醒,只是通知,不会释放o对象之前的锁

模拟这样一个需求
    仓库采用LIst集合。
    保证仓库永远只有一个元素,达到生产一个消费一个

*/

public class ThreadSHX {
    public static void main(String[] args) {
        List list = new ArrayList() ;
        //创建两个线程对象
        //生产者
        Producer producer = new Producer(list);
        Thread t1= new Thread(producer);
        //消费者
        Consumer consumer = new Consumer(list);
        Thread t2= new Thread(consumer);

        t1.setName("生产者线程");
        t2.setName("消费者线程");

        t1.start();
        t2.start();
    }
}
//生产线程
class Producer implements Runnable{
    private List list;  //仓库

    public Producer(List list) {
        this.list=list;
    }

    @Override
    public void run() {
        //一直生产
        while(true){
            synchronized (list) {
                if (list.size() > 0)
                //当前线程进入等待状态
                {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Object obj = new Object();
                list.add(obj);
                System.out.println(Thread.currentThread().getName() + "---->" + obj);
                list.notify();
            }
        }
    }
}
//消费线程
class Consumer implements Runnable{
    private List list;  //仓库

    public Consumer(List list) {
        this.list=list;
    }

    @Override
    public void run() {
        //一直消费
        while(true){
            synchronized (list){
                if(list.size()==0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Object obj = list.remove(0);
                System.out.println(Thread.currentThread().getName()+"---->" + obj);
                list.notifyAll();
            }
        }
    }
}

你可能感兴趣的:(Java,SE基础)