多线程
什么是多线程?
首先要了解进程,一个进程可以启用多个线程。
进程:
1.可以看做一个公司,线程就是公司的员工。
2.进程A和进程B的内存资源独立不共享
3.进程是线程的执行单元
线程:
1.线程A与线程B之间堆内存和方法区共享,栈是独立的,一个线程一个栈。
2.那假设启用10个线程,每个线程都对应一个栈,栈与栈之间互不干扰
这就是多线程并发,多线程并发提高效率
就是,单核中里面的线程要抢占时间片,两个线程来回切换,来回抢占,导致人有一种‘两个线程在同时进行的‘错觉’’。
。实际上,单核在一个时间点上只能执行一个线程。
5..run与.start的区别(也是并发并行的区别!!!!)
很有趣
s
弹幕讲的好啊,记录一下
6.线程生命周期
分为哪几种?
新建状态
就绪状态
运行状态
阻塞状态
死亡状态
掌握方法:
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(); } } } }