多线程

什么是多线程?

首先要了解进程,一个进程可以启用多个线程。

进程:  

    1.可以看做一个公司,线程就是公司的员工。
    2.进程A和进程B的内存资源独立不共享

    3.进程是线程的执行单元

线程:

    1.线程A与线程B之间堆内存和方法区共享栈是独立的,一个线程一个栈。

    2.那假设启用10个线程,每个线程都对应一个栈,栈与栈之间互不干扰

       这就是多线程并发,多线程并发提高效率

 

 

 就是,单核中里面的线程要抢占时间片,两个线程来回切换,来回抢占,导致人有一种‘两个线程在同时进行的‘错觉’’。

。实际上,单核在一个时间点上只能执行一个线程。

5..run与.start的区别(也是并发并行的区别!!!!)

很有趣

 

 s

弹幕讲的好啊,记录一下

 

 

 6.线程生命周期

分为哪几种?

     新建状态

    就绪状态

    运行状态

    阻塞状态

    死亡状态

 

 

 掌握方法:

  Thread.currentThread();//获取当前线程对象
  t.getName;//获取线程名字(默认为Thread-0....++)
  t.setName;//更改线程对象名;
  t.start();//分支一个线程创建一个栈出来,该栈栈帧是run方法。
  Thread.sleep( long ,int );//使当前线程睡眠1000毫秒*int
  t.interrupt();//唤醒线程:制造异常,使线程被trycatch捕捉抛出,中断睡眠。
  t.stop();//(已过时)强行结束线程,缺点:可能会导致线程内未保存数据丢失。
  在实现接口的类里创建一个布尔型变量来控制run方法if(布尔),如果想停止线程,可以在main里将布尔类型改成false,这样当main中执行到该语句时,run也就停止了,                   需要注意的是,要将该类new出来,不能直接写到线程里。

 

package IOtext;
public class ThreadText01 implements Runnable {
   public boolean run=true;
    public void run() {
            for (int i=0;i<100;i++)
            {
                if(run)//若run==false则该线程退出
                {
                System.out.println(Thread.currentThread().getName()+"->"+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
                else
                    return;
        }
    }
    public static void main(String[] args) {
        ThreadText01 r=new ThreadText01();
        Thread t=new Thread(r);
        t.start();
        t.setName("001");
        for (int i=0;i<5;i++)
        {
            try {
                Thread.sleep(1000*1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread()+"->"+i);
        }
        r.run=false;//停止
    }
}

7.线程调度(了解内容)

 8.线程安全(重点)

 

 

package Thread.ThreadSafe;

public class BankAcd extends Thread{
    private String id1;
    private int uesrmoney;

    public BankAcd(String id1, int uesrmoney) {
        this.id1 = id1;
        this.uesrmoney = uesrmoney;
    }
    public BankAcd(){}



    public String getId1() {
        return id1;
    }

    public void setId(String id) {
        this.id1 = id;
    }

    public int getUesrmoney() {
        return uesrmoney;
    }

    public void setUesrmoney(int uesrmoney) {
        this.uesrmoney = uesrmoney;
    }

    public void quqian(int money) {
        synchronized (this){
            try {
                this.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            int quqian= this.uesrmoney - money;
            this.setUesrmoney(quqian);
        }

    }



}

 

 synchronized (this)//这个是当有共享对象时,线程需要等;
 synchronized (“dada”)//这个创建了一个字符串,因为字符串对象存储在字符串常量池里,所以所有的对象都可以使用它。
 

 

 

 

 

死锁

// synchronized嵌套发生死锁,一般不建议这么写
package Thread;
public class DeahLock {
    public static void main(String[] args) {
        Object a=new Object();
        Object b=new Object();
        Thread a1=new MyThread1(a,b);
        Thread b1=new MyThread2(a,b);
        a1.setName("a1");
        b1.setName("b1");
        a1.start();
        b1.start();
    }

}
class MyThread1 extends Thread{
    Object O1;
    Object O2;
    public MyThread1(Object a,Object b){
        this.O1=a;
        this.O2=b;
    }


    public void run() {
    synchronized (O1){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        synchronized (O2){


        }
    }
    }
}
class MyThread2 extends Thread{
    Object O1;
    Object O2;
    public MyThread2(Object a,Object b){
        this.O1=a;
        this.O2=b;
    }


    public void run() {
        synchronized (O2){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (O1){


            }
        }
    }
}

 9.1守护线程(后台线程)

java一共有两种线程,一个是守护,一个是用户线程。

具有代表性的:gc垃圾回收器。

守护线程特点:

一般守护线程是个死循环,用户线程结束则守护结束。

ps:主线程main方法是用户线程。

守护线程用在什么地方?

守护,偏后台

代码格式:

     a.setDaemon(true);//将a线程对象设置成守护线程。

 

package Thread;
public class ThreadText02 {
    public static void main(String[] args) {
        Thread a=new T();
        a.setName("a");
        a.setDaemon(true);
        a.start();
        for (int i=0;i<10;i++)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread().getName()+"->"+i);
        }
    }
}
class  T extends Thread{
int i=0;
//当用户线程结束,守护线程自动终止。
public void run() {
       while (true)
        {
            i++;
            try {
                T.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread().getName()+"->"+i);
        }
    }
}

 2.定时器

什么是定时器?

间隔特定时间,执行特定程序。

在实际开发中每隔一段时间执行一段程序是很常见的。

在java中可以采用多种方式实现:

      1.使用sleep方法,设置睡眠时间,睡眠结束后醒来执行。

      2.java类库中已经写好了定时器,使用java.until.Timer,可以直接使用

      3.一般高级框架中都实现了定时,比如Spring。

Timer

schedule(定时任务对象(继承TimerTask)这里也可以用匿名抽象类,开始,间隔时间)

 

代码如下:

 

    

package Thread.ThreadSafe;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerText01 {
    public static void main(String[] args) throws Exception{
        Timer a=new Timer();//创建定时器
        SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//定义日期格式
        Date first=s.parse("2022-05-17 11:11:50");//解析字符串
        a.schedule(new text(),first,1000*5);//定时任务间隔时间
    }
}
class text extends TimerTask {
    public void run() {
        SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String f1=s.format(new Date());
        System.out.println(f1+"完成备份");
    }
}

//间隔5秒。

 3.实现线程的第三种方式:实现Callable接口

前两种是什么??

D:继承Thread和实现Runnable接口。

Callable接口有什么特点呢?

优点:它的线程可以返回一个值。前两种都是void型的。

缺点:如果要返回值的话,需要等待call运行结束返回值.get(),影响效率。

package Thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class CallableThreadText {
    public static void main(String[] args) throws Exception{
        //第一步,创建一个“未来任务类对象”
     //FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
       FutureTask f=new FutureTask(new Callable() {//匿名内部类         //call方法就相当于run方法,只不过这个有返回值。 public Object call() throws Exception { System.out.println("call begin"); Thread.sleep(1000*5); int a=5,b=10; System.out.println("call over"); return a+b;//自动装箱变成Intger } }); Thread t=new Thread(f);//创建线程对象 t.start(); Object a1=f.get();//得到call的返回值,get方法会使main阻塞,call结束后main才能继续执行。 System.out.println(a1); } }

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

第一,wait和notify方法不是线程对象独有方法,是java中任何一个java对象都有的方法,因为这两方法是object类自带的。

wait方法和notify方法不是通过线程调用的,t.wait【×】t.notify【×】。

第二,wait()方法作用?

 

    Object o=new Object ();

    o.wait();

 

    表示:

    让正在o对象上的活动进入等待状态,无限等待,直到被唤醒,而sleep是线程特有方法,并是有限等待。

    o.wait();方法调用,会让当前正在o对象上活动的线程进入等待状态。

第三,notify()方法作用?

    Object o=new object();

    o.notify();

    表示:

        唤醒正在o对象上等待的线程。

    还有个notifyAll()方法,这是让在o上等待的线程全部唤醒。

 

 

 

生产者与消费者(生产者产一个,消费者消耗一个)

package Thread;
import java.util.ArrayList;
import java.util.List;
public class ThreadText03 {
    public static void main(String[] args) {
        List list=new ArrayList();
        Thread a1=new Thread(new Producer(list));
        Thread b1=new Thread(new Consumer(list));
        a1.setName("Producer");
        b1.setName("consumer");
        a1.start();
        b1.start();
    }
}
class  Producer implements Runnable{
    private  List list;
    public Producer(List l){
        this.list=l;
    }
    @Override
    public void run() {

        while (true)
        {
            synchronized (list){
                if(list.size()>0)
                {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }

                Object o=new Object();
                list.add(o);
                System.out.println(Thread.currentThread().getName()+"->"+o);
                list.notifyAll();

            }

        }
    }
}
class  Consumer implements Runnable{
        private  List list;
public Consumer(List i)
{
    this.list=i;
}
    @Override
    public void run() {
        while (true)
        {
            synchronized (list){
                if(list.size()==0)
                {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }

                Object o=new Object();
                list.remove(0);
                System.out.println(Thread.currentThread().getName()+"->"+o);
                list.notifyAll();
            }

        }
    }
}

 

posted @ 2023-05-19 15:06  22软工冷薄  阅读(10)  评论(0编辑  收藏  举报