当前位置: 首页 > wzjs >正文

齐诺网站建设东莞网站建设做网站河南最新消息

齐诺网站建设东莞网站建设做网站,河南最新消息,中国500强企业排名,自学建筑app第八章:多线程 8-1 基本概念:程序、进程、线程 (了解即可) 程序(program):一段静态代码,静态对象。为了完成特定任务、用某种语言编写的一组指令的集合 进程(process&am…

第八章:多线程



8-1 基本概念:程序、进程、线程 (了解即可)


程序(program):一段静态代码,静态对象。为了完成特定任务、用某种语言编写的一组指令的集合

进程(process):是程序的一次执行过程,或是在运行的一个程序

线程(thread):进程可以进一步细化为线程,是一个程序内部的一条执行路径

线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc)

并行与并发:

并行:多个 CPU 同时执行多个任务

并发:一个 CPU 同时执行多个任务

并发:一个 CPU 同时执行多个任务 比如:秒杀、多个人做同一件事



8-2 线程的创建和使用


方式一、继承于 Thread 类

1、创建一个继承于 Thread 类的子类

2、重写 Thread 类的run()

3、创建 Thread 类的子类对象

4、通过此对象调用 start()

我们不能直接调用对象.run()来启动线程

不可以让已经 start 的线程再去执行一个新的线程;我们需要重新创建一个线程的对象

用代码来演示一下过程

/*** 多线程的创建,方式一:继承于 Thread 类* @author Jackson_kcw* @create 2025-02-22*/
public class ThreadTest {public static void main(String[] args) {//3、创建 Thread类的子类的对象MyThread myThread = new MyThread();//4、通过次对象调用 start() :启动当前线程、调用当前线程的 run()myThread.start();}}
//1、创建一个继承于 Thread 类的子类
class MyThread extends Thread{//2、重写 Thread 类的 run()@Overridepublic void run() {for (int i = 0; i <100 ; i++) {//输出 100以内的偶数if(i%2==0){System.out.println(i);}}}
}

Thread 其中的方法

CleanShot 2025-02-22 at 16.37.14

yield():释放当前 CPU 的执行权

join():在线程 a 中调用线程 b 的 join 方法,此时线程 a 进入阻塞状态,直到线程 b 完全执行完之后,线程 a 才会结束阻塞状态

stop(): 强制结束当前线程

sleep(long millitime):让当前线程“睡眠”指定的 millitime 毫秒,在指定的时间内,当前线程为阻塞状态

线程的优先级:

1、优先级分类

MAX_PRIORITY: 10

MIN_PRIORITY:1

NORM_PRIORITY:5

2、

getPriority():获取线程的优先级

setPriority(int p):设置线程优先级

注:高优先级只是从概率上来说更可能会先执行,但不意味着绝对


方式二、创建多线程的方式二:实现 Runnable 接口

1、创建一个实现了 Runnable 接口的类

2、实现类去实现 Runnable 的抽象方法:run()

3、创建实现类的对象

4、将此对象作为参数传递到 Thread 类的构造器中,创建 Thread 类的对象

5、通过 Thread 类的对象调用 start()

代码例子:

package com.kcw.java1;/**创建多线程的方式二:实现 Runnable 接口* @author Jackson_kcw* @create 2025-02-23*/
public class ThreadTest1 {public static void main(String[] args) {//3、创建实现类的对象MThread thread = new MThread();//4、将此对象作为参数传递到 Thread 类的构造器中,创建 Thread 类的对象Thread t1=new Thread(thread);//5、通过 Thread 类的对象调用 start():启动线程;调用当前线程的 run()t1.start();}
}
//1、创建一个类实现了 Runnable 接口的方法
class MThread  implements Runnable{//2、实现类去实现 Runnable 中的抽象方法:run()@Overridepublic void run() {for (int i = 0; i <100 ; i++) {if(i%2==0){System.out.println(i);}}}
}

创建线程的两种方式的比较

开发中:优先选择:实现 Runnable 接口的方式

原因:1、实现的方式没有类的单继承性的局限性

​ 2、实现的方式更适合来处理多个线程共有数据的情况

联系:Thread 也是实现 Runnable

相同点:两者都需要重写 run 方法,将线程要执行的逻辑声明在 run()中



8-3 线程的生命周期


完整生命周期的几种状态

CleanShot 2025-02-23 at 14.13.00

线程生命周期

CleanShot 2025-02-23 at 14.21.02



8-4 线程的同步


线程安全问题:当某个线程在运行过程中,另一个线程进入运行状态,会影响到共享数据;如卖票 会出现负数情况

如何解决线程安全问题:当一个线程 a操作共享数据数据的时候,其他的线程不能参与进来,直到线程 a操作完共享数据,其他线程才可以开始操作共享数据,即使线程 a 出现阻塞,也不能改变

在 Java 中,我们通过同步机制,解决线程的安全问题

方式一:同步代码块

synchronized(同步监视器){

​ //需要被同步的代码

}

说明:1、操作共享数据的代码即为 需要被同步的代码 ---->不能包含代码多了,也不能包少了

​ 2、共享数据:多个线程共同操作的变量。比如卖票问题里面的 ticket

​ 3、同步监视器:俗称锁。任何一个类的对象都可以充当锁

要求:多个线程必须要共用一把锁

补充:在实现 Runnable接口创建多线程的方式中,我们可以考虑使用 this 充当同步监视器

在继承 Thread 类创建多线程的方式中,慎用使用 this 充当同步监视器,可以考虑使用当前类充当同步监视器

方法二:同步方法

如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步

1、同步方法仍然涉及到同步监视器,只是不需要我们显式声明

2、非静态的同步方法,同步监视器是:this

​ 静态的同步方法,同步监视器是:当前类本身

同步方法的格式如下代码:show()方法的格式

package java1;/*** @author Jackson_kcw* @Time 2025-02-23*/
public class WindowTest4 {public static void main(String[] args) {Window4 w = new Window4();Thread t1 = new Thread(w);Thread t2 = new Thread(w);Thread t3 = new Thread(w);t1.start();t2.start();t3.start();}
}
class Window4 implements Runnable{private static int ticket=100;@Overridepublic void run() {while(true){show();}}public synchronized void  show(){//同步方法  如果这个是继承 Thread 会创建几个对象,需要加 static 将此方法转为静态if(ticket>0){System.out.println(Thread.currentThread().getName()+"卖票:"+ticket);ticket--;}}
}

同步的方式,解决了线程的安全;但是在操作同步代码时,只能一个线程参与,其他线程等待,效率会低一点

补充:之前的单例模式中的懒汉解决线程安全问题

mac 电脑中 ide 包裹代码块的快捷键为:option+command+T

/**使用同步机制将单例模式里面的懒汉式改写成线程安全的* @author Jackson_kcw* @Time 2025-02-23*/
public class BankTest {}
class Bank{private Bank(){}private static Bank instance=null;public  synchronized Bank getInstance(){//方式一:效率不高
//        synchronized (Bank.class) {
//            if(instance==null){
//                instance=new Bank();
//                return instance;
//            }
//            else return instance;
//        }//方式二:效率更高if(instance==null){synchronized (Bank.class) {if(instance==null){instance=new Bank();}}}return instance;}}

死锁问题

CleanShot 2025-02-23 at 16.11.00

我们使用同步时,要避免死锁

解决线程安全问题的方式三:Lock 锁-------JDK5 新增的

例如:

package Lock;import java.util.concurrent.locks.ReentrantLock;/*** @author Jackson_kcw* @Time 2025-02-23  PM4:52*/
public class LockTest {public static void main(String[] args) {Window window=new Window();Thread thread1=new Thread(window);Thread thread2=new Thread(window);Thread thread3=new Thread(window);thread1.start();thread2.start();thread3.start();}
}
class Window implements Runnable{private int ticket=100;//1、实例化 ReentrantLockprivate ReentrantLock lock=new ReentrantLock();@Overridepublic void run() {while(true){//2、调用锁定方法 locklock.lock();try {if(ticket>0){System.out.println(Thread.currentThread().getName()+"卖票:"+ticket);ticket--;}else break;} finally {//3、调用解锁方法 unlock()lock.unlock();}}}
}
面试题:synchronized 于 Lock 的异同

相同:两者都是解决线程安全的方法

不同:synchronized 机制在执行完相应的同步代码以后,自动的释放同步监察器

​ Lock 需要手动的启动同步(lock()),同时结束同步也需要手动的实现解锁( unlock() )

优先使用的顺序

Lock–>同步代码块(已经进入了方法体,分配了相应资源)–>同步方法(在方法体之外)

如何解决线程安全问题?有哪几种方式

答:1、使用 synchronized 关键字,用于代码块或方法(即同步代码块、同步方法)

​ 2、使用 ReentrantLock(可重入锁),lock()与 unlock()手动设置锁和解除锁



8-5 线程的通信


线程通信涉及到三个方法:

wait():使线程进入阻塞状态,并释放同步监视器

notify():唤醒被 wait 的一个线程,如果有多个线程被 wait,就唤醒优先级高的

notifyAll():唤醒所有 wait 的线程

以下见代码例子:

package Java2Communication;/**线程通信的例子:使用两个线程打印 1-100.线程一、线程二交替打印* @author Jackson_kcw* @Time 2025-02-24  PM2:04*/
public class Communication {public static void main(String[] args) {Number n1=new Number();Thread t1=new Thread(n1);Thread t2=new Thread(n1);t1.setName("t1");t2.setName("t2");t1.start();t2.start();}
}
class Number implements Runnable{private int number=1;@Overridepublic void run() {while (true) {synchronized (this) {//唤醒 阻塞的线程notify();if(number<=100){System.out.println(Thread.currentThread().getName()+":"+number);number++;try {//使得调用如下wait()方法的线程进入阻塞状态wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else break;}}}
}

注意点

1、wait()、notify()、notifyAll()三个方法必须使用在同步代码块或同步方法中

2、这三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现 IllegalMonitorStateException异常

3、这三个方法都定义在 Java.lang.Object 类中

面试题

sleep()和 wait()的异同:

同:一旦执行方法,都可以使当前的线程进入阻塞状态

异:1、两个方法声明的位置不同:Thread 类中声明 sleep(),Object 类中声明 wait()

​ 2、调用的范围要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用在同步代码块

​ 3、关于是否释放同步监视器的问题:如果两个方法都用在同步代码块或同步方法中,sleep 不会释放 锁(同步监视器),但是 wait()会释放锁



8-6 JDK5.0 新增线程创建方式


新增方式一:实现 Callable 接口

CleanShot 2025-02-24 at 14.40.11

创建步骤:

1、创建一个实现 Callable 的实现类

2、实现 call 方法,将此线程需要执行的操作声明在 call()中

3、创建 Callable 接口实现类的对象

4、将此 Callable 接口实现类的对象作为参数传递到 FutureTask 构造器中,创建 FutureTask 的对象

5、将 FutureTask 的对象作为参数传递到 Thread类的构造器中,创建 Thread 对象,并调用 start();

6、获取 Callable 中的 call 方法的返回值

在代码中如下:

package Java3;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/**创建线程的实现方式三:实现 Callable接口* @author Jackson_kcw* @Time 2025-02-24  PM2:40*/
public class ThreadNew {public static void main(String[] args) {//3、创建 Callable 接口实现类的对象NumberThread numberThread = new NumberThread();//4、将此 Callable 接口实现类的对象作为参数传递到 FutureTask 构造器中,创建 FutureTask 的对象FutureTask futureTask= new FutureTask(numberThread);//5、将 FutureTask 的对象作为参数传递到 Thread类的构造器中,创建 Thread 对象,并调用 start();new Thread(futureTask).start();try {//6、获取 Callable 中的 call 方法的返回值//get()返回值即为 FutureTask 构造器参数 Callable 实现类重写的 call()的返回值Object sum=futureTask.get();System.out.println("总和为:"+sum);} catch (InterruptedException e) {throw new RuntimeException(e);} catch (ExecutionException e) {throw new RuntimeException(e);}}
}
//1、创建一个实现 Callable 的实现类
class NumberThread implements Callable {//2、实现 call 方法,将此线程需要执行的操作声明在 call()中@Overridepublic Object call() throws Exception {int sum=0;for (int i = 1; i <=100 ; i++) {if(i%2==0){System.out.println(i);sum+=i;}}return sum;}
}

二、如何理解实现 Callable 接口的方式创建多线程比实现Runnable接口要强大

1、call()方法可以有返回值

2、call()方法可以抛出异常,被外面的操作捕获,获取异常信息

3、Callable 是支持泛型的


新增方式二:使用线程池

CleanShot 2025-02-24 at 15.18.45

CleanShot 2025-02-24 at 15.32.57


利用线程池方式创建线程的步骤:

1、提供指定线程数量的线程池

2、执行指定的线程的操作。需要提供实现 Runnable 或 Callable 接口的实现类

3、关闭连接池子

具体的代码例子

package Java3;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;/**创建线程的方式四:使用线程池的方式* @author Jackson_kcw* @Time 2025-02-24  PM3:31*/
public class ThreadPool {public static void main(String[] args) {//1、提供指定线程数量的线程池ExecutorService executorService = Executors.newFixedThreadPool(10);//2、执行指定的线程的操作。需要提供实现 Runnable 或 Callable 接口的实现类executorService.execute(new NumberThread2());//适合使用于 RunnableexecutorService.submit(new FutureTask(new NumberThread1())); //适合适用于 CallableexecutorService.shutdown();//3、关闭连接池子}}
class NumberThread1  implements  Callable {@Overridepublic Object call() throws Exception {for (int i = 0; i < 100; i++) {if (i % 2 != 0) {System.out.println(Thread.currentThread().getName()+"  "+i);}}return null;}}
class NumberThread2 implements Runnable {@Overridepublic void run() {for (int i = 0; i <= 100; i++) {if (i % 2 == 0) {System.out.println(Thread.currentThread().getName() + " " + i);}}}
}

面试题:创建多线程的方式?四种

方式一、继承于 Thread 类

方式二、实现 Runnable 接口

方式三:实现 Callable 接口

方式四:使用线程池(实际开发中常用)




文章转载自:

http://tB6nRxrJ.fmjfz.cn
http://yhbodQPJ.fmjfz.cn
http://WvUqpHJ7.fmjfz.cn
http://2RYY6mpc.fmjfz.cn
http://JaHOjCer.fmjfz.cn
http://Hn4AoMLu.fmjfz.cn
http://h5TYcRY0.fmjfz.cn
http://cgfi90G7.fmjfz.cn
http://tPhoc5y0.fmjfz.cn
http://84axBMur.fmjfz.cn
http://UJtWDPhg.fmjfz.cn
http://PmsNLj0g.fmjfz.cn
http://VAmC9uct.fmjfz.cn
http://ln0g8fAv.fmjfz.cn
http://7vkmgsge.fmjfz.cn
http://vIeI1Kjz.fmjfz.cn
http://IGYGPbK3.fmjfz.cn
http://hNcR7mHx.fmjfz.cn
http://p4KWGiZT.fmjfz.cn
http://k5PpvB8f.fmjfz.cn
http://vaUvi5s9.fmjfz.cn
http://kWECd6Jn.fmjfz.cn
http://pnuXOXso.fmjfz.cn
http://mQ3bb24z.fmjfz.cn
http://n1s61lZN.fmjfz.cn
http://t93YADAw.fmjfz.cn
http://589128fA.fmjfz.cn
http://wfLiU62j.fmjfz.cn
http://S0RFgDbu.fmjfz.cn
http://KVuCmip8.fmjfz.cn
http://www.dtcms.com/wzjs/753014.html

相关文章:

  • 网站开发就业前景怎么样江苏省建设信息网站管理平台
  • 网站建设教程设制作网站要花多少钱
  • 宗亲网站开发简洁大方网站模板
  • 选择佛山网站设计常用的搜索引擎网站
  • flash网站教程网站建设费用要摊销嘛
  • 软件开发 网站建设网站开发子账号
  • 沈阳中小企业网站建设福田网站优化
  • 无形资产 网站开发做刷单网站违法吗
  • 网站开发专员网站改版重新备案
  • 做外贸网站选择服务器wordpress 论坛
  • 企业网站建设存在的典型问题有哪些?申请免费空间
  • cms做视频网站上海传媒公司电话
  • 电商如何推广网站优化软件排名器
  • 深圳网站开发培训价格自己做游戏的 网站
  • dw5怎样做网站网站打包app
  • 长沙第三方网站建设公司seo怎么优化方案
  • 电影网站开发PPT模板网站推广免费推广网站
  • 网站建设价格请咨询兴田德润天津做网站找哪家好
  • 免费php mysql网站hexo wordpress 主题制作
  • 个人网站介绍模板下载phpmysql网站开发技术
  • 比较有名的diy制作网站页游排行
  • 查询网站备案时间查询网站开发人员的水平
  • 网站建设使用的什么语言wordpress备份 ftp
  • 四川网站建设培训班章丘营销型网站设计公司
  • 大连大连建设工程信息网站怎么建立一个网站能够与讯飞云对话
  • 商城类网站怎么优化青岛网站域名备案
  • 北京网站建设技术托管公司网站建设怎么规划比较好
  • 网站流量指标网页设计师介绍
  • 广东建设执业网站开发h5网站开发
  • 怎么创建网站自己创建汕头网站设计怎么做