多线程

您所在的位置:网站首页 双胎输血综合症胎儿保住的几率大吗 多线程

多线程

2023-07-09 06:55| 来源: 网络整理| 查看: 265

了解多线程 并发和并行

进程和线程

总结 多线程的实现方式--继承Thread

实现步骤 package com.thread; public class MyThread extends Thread{ @Override public void run(){ //run()里面的代码就是线程开启之后执行的代码 for (int i = 0; i < 100; i++) { System.out.println("线程开始了"+i); } } } package com.thread; public class Test { public static void main(String[] args) { MyThread myThread = new MyThread();//线程1 MyThread myThread1 = new MyThread();//线程2 myThread.start();//开启线程1 myThread1.start();//开启线程2 } }

我们从一个线程的执行可能开不出来什么,什么我们同时开启了2个线程。可以看到这2个线程在并发交替执行

2个小问题

多线程的实现方式--实现Runnable接口

Thread构造方法里面传递的参数,表示线程执行对应myrnnnable的run 方法

实现步骤 package com.runnable; public class MyRunnableTest { public static void main(String[] args) { //创建了一个参数的对象 MyRunnable myRunnable = new MyRunnable(); //创建了一个线程的的对象并把参数传递给它 Thread thread = new Thread(myRunnable); //开启线程 //创建并执行线程2 thread.start(); MyRunnable myRunnable1 = new MyRunnable(); Thread thread1 = new Thread(myRunnable1); thread1.start(); } } package com.runnable; public class MyRunnable implements Runnable{ @Override public void run() { //表示线程启动后执行的代码 for (int i = 0; i < 100; i++) { System.out.println("线程开始了"+i); } } }

多线程的实现方式--实现callable接口

package com.callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { //线程开启后需要执行里面的cll方法 MyCallable myCallable = new MyCallable(); //Thread thread = new Thread(myCallable);不能直接将myCallable传递给Thread //1.FutureTask的泛型和MyCallable的泛型相同 //2.将MyCallable传递给FutureTask //可以获取线程执行结束之后的结果 FutureTask future = new FutureTask(myCallable); //将FutureTask传递给Thread Thread thread = new Thread(future); thread.start(); //获取线程执行结束的结果 final String reason = future.get(); System.out.println(reason); } } package com.callable; import java.util.Objects; import java.util.concurrent.Callable; public class MyCallable implements Callable {//泛型类型表示返回值的数据类型 //返回值表示线程运行结束之后的结果 @Override public String call() throws Exception { return "hell world"; } } ouput:hello world

注意:当我们的get()方法在我们t1.start()线程开启之前执行,此时我们将不可能获取到线程执行的结果。并且由于get()方法 当线程还没有执行结束将会一直处于等待状态。当我们将get方法放在get之前,此时我们的程序将一直停留在get()处,不会继续运行

三种实现方式的对比

Thread方式--设置获取名字

通过构造方法设置线程名 我们Mythread的父类是有类似Thread(String name)的构造方法专门用来设置线程名的,但是由于构造方法不能继承,所有我们的子类要想使用设置线程名的构造方法来创建子类的话,就需要在MyThread中创创建单参构造并调用父类单参构造 Thread方法--获取线程对象

获取当先线程对象的一般使用场景

Thread----sheep方法

异常小计 如果一个类或者接口里面的方法没有抛出异常,那么这个类或者接口的实现类所重写的方法也不能抛出异常 线程的优先级

优先级的获取和设置

1.优先级1-10,默认为5

2.线程优先级越高,只能说抢到cup的概率越高,不是只可能是该线程执行** package com.callable; import java.util.concurrent.Callable; public class MyCallable1 implements Callable { @Override public String call() throws Exception { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"线程开始了"+i); } return null; } } package com.callable; import java.util.concurrent.FutureTask; public class Test1 { public static void main(String[] args) { //线程1 MyCallable1 myCallable = new MyCallable1(); FutureTask futureTask = new FutureTask(myCallable); Thread thread = new Thread(futureTask); System.out.println(thread.getPriority());//默认5 //线程2 MyCallable1 myCallable2 = new MyCallable1(); FutureTask futureTask2 = new FutureTask(myCallable2); Thread thread2 = new Thread(futureTask2); System.out.println(thread2.getPriority());//默认5 //设置线程名 thread.setName("飞机"); thread2.setName("坦克"); //启动线程 // thread2.start(); //thread.start(); } } Thread方法--守护线程 解释

我们将QQ里面的聊天和传递文件看成是2个线程,如果我们将QQ关闭,聊天和传递文件也会随之关闭,没有存在的必要了。聊天和传递文件就是2个守护线程

package com.thread; public class MyThread1 extends Thread{ @Override public void run(){ for (int i = 0; i < 100; i++) { System.out.println(currentThread().getName()+"线程开始了"+i); } } } package com.thread; public class Test1 { public static void main(String[] args) { //守护线程:当普通线程执行完了,守护线程也没有继续运行下去的必要了 MyThread1 myThread1 = new MyThread1(); MyThread1 myThread2 = new MyThread1(); myThread1.setName("女神"); myThread2.setName("备胎"); myThread2.setDaemon(true);//将第二个线程设置成守护线程 myThread1.start(); myThread2.start(); } }

02线程安全问题 线程安全问题--买票案例的实现

package com.itheima.threadsecture; public class Ticket implements Runnable { private int ticketCount = 100;//剩下的票数 @Override public void run() { while (true){ if(ticketCount>0){ ticketCount--; System.out.println(Thread.currentThread().getName()+"正在出售票"+"还剩下"+ticketCount); }else { //当票数为0时,线程结束 break; } } } } package com.itheima.threadsecture; public class TicketDemo { public static void main(String[] args) { //Ticket作为参数相当于是要执行的内容 //各个线程的参数必须一致,要不然将会出现3份票数 Ticket ticket = new Ticket(); Thread thread1 = new Thread(ticket); Thread thread2 = new Thread(ticket); Thread thread3 = new Thread(ticket); thread1.setName("窗口1"); thread2.setName("窗口2"); thread3.setName("窗口3"); thread1.start(); thread2.start(); thread3.start(); } }

线程安全--原因分析

在Ticket类中增加延迟 package com.itheima.threadsecture; public class Ticket implements Runnable { private int ticketCount = 100;//剩下的票数 @Override public void run() { while (true){ if(ticketCount>0){ try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } ticketCount--; System.out.println(Thread.currentThread().getName()+"正在出售票"+"还剩下"+ticketCount); }else { //当票数为0时,线程结束 break; } } } }

出现线程安全的原因

本质上是多个线程操作共享数据 同步代码块解决线程安全

用同步代码块实现购票代码

我们将操作共享资源的代码放在同步代码块中 package com.itheima.threadsecture; public class Ticket implements Runnable { private int ticketCount = 100;//剩下的票数 private Object obj = new Object(); @Override public void run() { while (true){ synchronized (obj) {//锁对象是任意的,但是必须保证各个线程面对的是同一把锁 if(ticketCount>0){ try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } ticketCount--; System.out.println(Thread.currentThread().getName()+"正在出售票"+"还剩下"+ticketCount); }else { //当票数为0时,线程结束 break; } } } } } package com.itheima.threadsecture; public class TicketDemo { public static void main(String[] args) { //Ticket作为参数相当于是要执行的内容 //各个线程的参数必须一致,要不然将会出现3份票数 Ticket ticket = new Ticket(); Thread thread1 = new Thread(ticket); Thread thread2 = new Thread(ticket); Thread thread3 = new Thread(ticket); thread1.setName("窗口1"); thread2.setName("窗口2"); thread3.setName("窗口3"); thread1.start(); thread2.start(); thread3.start(); } }

线程安全问题--锁对象唯一 同步方法

证明同步方法的锁对象是this package com.runnable; public class MyRunnable1 implements Runnable{ private int ticketCount = 100;//剩下票数 @Override public void run() { while (true) { if("窗口1".equals(Thread.currentThread().getName())){ try { synchronizedMethod(); } catch (InterruptedException e) { throw new RuntimeException(e); } if("窗口2".equals(Thread.currentThread().getName())){ synchronized (this){//锁对象为当前调用的对象 if(ticketCount


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3