线程剩余内容

1:死锁:

    synchronized在开发中最好不要嵌套使用,可能导致死锁。

public class SiSuo01 {
    public static void main(String[] args) {
        //将o1和o2new出来
        Object o1 = new Object();
        Object o2 = new Object();

        //将o1和o2传给线程,t1t2共享o1o12
        Thread t1 = new MyThread1(o1,o2);
        Thread t2 = new MyThread2(o1,o2);

        //创建线程
        t1.start();
        t2.start();


    }
}
class MyThread1 extends Thread{
    Object o1;
    Object o2;
    public MyThread1(Object o1,Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }


    public void run() {
        synchronized (o1){
            //如果添加sleep方法
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){

            }

        }

    }
}
class MyThread2 extends Thread {
    Object o1;
    Object o2;

    public MyThread2(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        synchronized (o2){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){

            }

        }
    }
}

线程剩余内容

2:开发中应该怎么解决线程安全问题?

2.1:是不是一上来就使用线程同步?synchronized

      并不是,synchronized会让执行效率降低,用户体验降低,系统的用户吞吐量降低(并发性),不得已使用synchronized。

2.2: 经量将局部变量代替实例变量,静态变量。

2.3:如果必须使用实例变量,那么可以创建多个对象,这样内存就不会共享(一个线程对应一个对象,100个线程对应100个对象对象不共享,就没有线程安全问题!!)

2.4:如果不能使用局部变量,对象也不能创建多个,这个时候使用synchronized,线程同步机制。

 

3:守护线程:

    3.1:java语言线程分为两大类:

           一类:用户线程

           一类:守护线程

           其中最具代表性是:垃圾回收机制(守护线程)。

    3.2:守护线程特点:

           一般守护线程是一个死循环,所以用户线程只有一结束,守护线程自动结束。

           注:主线程main方法是一个用户线程

    3.3:守护线程用在什么地方?

          每天零点时候系统数据自动备份。

          这个时候使用定时器,我们可以将定时器设置守护线程。

    3.4:守护线程代码实现!!!!!!!!!!

publicclassShoHuXianCheng {
   publicstaticvoidmain(String[] args) {
       //将线程new出来
       Threadt=newMyThread3();
       t.setName("备份线程");

       //启动线程的时候:将线程设置为守护线程
       t.setDaemon(true);
       t.start();

       //主线程:主线程是一个用户线程
       for (inti=0; i<10; i++) {
           System.out.println(Thread.currentThread().getName()+"---->"+i);
           try {
               Thread.sleep(1000);
          } catch (InterruptedExceptione) {
               e.printStackTrace();
          }
      }
  }
}
classMyThread3extendsThread{
   @Override
   publicvoidrun() {
       inti=0;
       //定义一个死循环
       while (true){
           System.out.println(Thread.currentThread().getName()+"--->"+(++i));
           try {
               Thread.sleep(1000);
          } catch (InterruptedExceptione) {
               e.printStackTrace();
          }
      }
  }
}

4:定时器:

   4.1作用:

         间隔特定的时间,执行特定的程序!!

   4.2:概述:

          数据备份,在实际开发中,每隔多久执行一段特定程序。

          可以使用sleep设置但太low了,在java类库中java.util.Timer,高级框架都支持。

          使用较多spring框架中提供SpringTask框架

   4.3:定时器的实现;

publicclassDingShiQi {
   publicstaticvoidmain(String[] args) throwsParseException {
       //创建一个定时器
       Timertimer=newTimer();
       //Timer timer = new Timer(trun);(守护线程方式)

       //指定定时方式
       //timer.schedule(定时任务,第一次执行时间,间隔多久执行一次);
       SimpleDateFormatsdf  =  newSimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS") ;
      DatefirstTime=  sdf.parse("2021-04-15 10:18:04");//将字符串转换为数字
     // timer.schedule(new logTimerTask(),firstTime,period);
       timer.schedule(newLogTimerTask(),firstTime, 1000);
  }
}
classLogTimerTaskextendsTimerTask{
   @Override
   publicvoidrun() {
       SimpleDateFormatsdf  =  newSimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS") ;
       Stringstr=sdf.format(newDate());
       System.out.println(str+"成功完成一次数据备份!");
  }
}

5:实现线程的第三种方法:实现Callable接口

5.1:优点:可以取得线程的执行结果

   缺点:效率低,在获取线程执行结果时,当前线程阻塞,效率低。

  5.2:代码实现:

importjava.util.concurrent.Callable;
importjava.util.concurrent.ExecutionException;
importjava.util.concurrent.FutureTask;

publicclassThreadTest15 {
   publicstaticvoidmain(String[] args) throwsExecutionException, InterruptedException {
       //第一步:创建一个“未来任务类”对象
       FutureTasktask=newFutureTask(newCallable() {
           @Override
           publicObjectcall() throwsException {  //call()方法相当于run方法,只不过这个有返回值
               //线程执行一个任务,执行之后会有一个结果
               System.out.println("begin");
               Thread.sleep(1000);
               System.out.println("end");
               inta=100;
               intb=200;
               returna-b;  //自动装箱
          }
      });
       //创建线程对象
       Threadt=newThread(task);

       //启动线程
       t.start();

       //这里是main方法,主线程
       //怎么获取
       //get()方法执行导致“当前线程堵塞”一直getget只有等到主线程结束才行
       Objectobj=task.get();
       System.out.println("牛啊"+obj);

       System.out.println("l");

      }
}

6:关于Object类中wait和notify方法。(生产者和消费者模式!)

   6.1:wait和notify方法不是线程对象方法,是java任何一个java对象都有的方法,因为这是Object中自带的

            wait和notify不是通过线程对象调用,不是t.wait或者t.notify

            wait作用?

            Object o = new Object();

            o.wait();

            表示:让o对象上活动的线程进入1等待状态,无期限等待。o.wait()方法使线程进入等待状态!!

            notify作用:唤醒被0.wait()使睡觉的方法。

            Object o = new Object();

             o.notify(),还有一个notifyAll()方法,唤醒所以等待线程!!

线程剩余内容

7.生产者与消费者代码实现!!!

packagecom.bjpowernode.java.threadsafe;

importjava.awt.*;
importjava.util.ArrayList;
importjava.util.List;

publicclassWiatDanNotify {
   publicstaticvoidmain(String[] args) {
       //创建一个仓库对象
       Listlist=newArrayList();
       //创建两个线程对象
       //生产线程
       Threadt1=newThread(newProducer(list));
       //消费者线程
       Threadt2=newThread(newConsumer(list));

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

       t1.start();
       t2.start();

  }
}
//上产线程
classProducerimplementsRunnable{
   //仓库
   privateListlist;

   publicProducer(Listlist){
       this.list=list;
  }

   @Override
   publicvoidrun() {
       //一直生产
       while (true){
           synchronized (list){
           if (list.size() >0) {
               try {
                   list.wait();
              } catch (InterruptedExceptione) {
                   e.printStackTrace();
              }
          }
           //程序能够运行到这说明仓库空了,可以生产
               Objectobj=newObject();
           list.add(obj);
               System.out.println(Thread.currentThread().getName()+"-->"+obj);
               //唤醒消费者进行消费
               list.notifyAll();
          }
      }
  }
}
classConsumerimplementsRunnable{
   //仓库
   privateListlist;

   publicConsumer(Listlist){
       this.list=list;
  }

   @Override
   publicvoidrun() {
       //一直生产
       while (true){
           //一直消费
           synchronized (list){
               if (list.size() ==0) {
                   try {
                       list.wait();
                  } catch (InterruptedExceptione) {
                       e.printStackTrace();
                  }
              }
               //程序能够运行到这说明仓库有数据,可以消费
               Objectobj=list.remove(0);
               list.add(obj);
               System.out.println(Thread.currentThread().getName()+"-->"+obj);
               //唤醒消费者进行生产
               list.notifyAll();
          }
      }
  }
}
//消费线程

  7.1:使用wait方法和notify方法实现”生产者和消费者模式“。

  7.2:什么是“生产者和消费者模式”?

          生产者负责生产,消费者负责消费;

          生产线程和消费线程达到均衡;

          特殊情况使用wait和notify。

  7.3:wait和notify不是线程对象方法,是普通java对象都有方法

  7.4:建立在同步基础之上,因为多线程要用时操作一个仓库

  7.5:作用:让o对象线程进入等待状态,并且释放对象锁。o.notify让等待线程唤醒。

上一篇:with欺骗作用域


下一篇:JAVA内部类