「java多线程写的」Java 多线程编程

博主:adminadmin 2022-11-30 11:36:10 55

今天给各位分享java多线程写的的知识,其中也会对Java 多线程编程进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

什么是Java多线程编程?

一、 什么是多线程:

我们现在所使用操作系统都是多任务操作系统(早期使用的DOS操作系统为单任务操作系统),多任务操作指在同一时刻可以同时做多件事(可以同时执行多个程序)。

多进程:每个程序都是一个进程,在操作系统中可以同时执行多个程序,多进程的目的是为了有效的使用CPU资源,每开一个进程系统要为该进程分配相关的系统资源(内存资源)

多线程:线程是进程内部比进程更小的执行单元(执行流|程序片段),每个线程完成一个任务,每个进程内部包含了多个线程每个线程做自己的事情,在进程中的所有线程共享该进程的资源;

主线程:在进程中至少存在一个主线程,其他子线程都由主线程开启,主线程不一定在其他线程结束后结束,有可能在其他线程结束前结束。Java中的主线程是main线程,是Java的main函数;

二、 Java中实现多线程的方式:

继承Thread类来实现多线程:

当我们自定义的类继承Thread类后,该类就为一个线程类,该类为一个独立的执行单元,线程代码必须编写在run()方法中,run方法是由Thread类定义,我们自己写的线程类必须重写run方法。

run方法中定义的代码为线程代码,但run方法不能直接调用,如果直接调用并没有开启新的线程而是将run方法交给调用的线程执行

要开启新的线程需要调用Thread类的start()方法,该方法自动开启一个新的线程并自动执行run方法中的内容

请点击输入图片描述

结果:

请点击输入图片描述

java多线程的启动顺序不一定是线程执行的顺序,各个线程之间是抢占CPU资源执行的,所有有可能出现与启动顺序不一致的情况。

CPU的调用策略:

如何使用CPU资源是由操作系统来决定的,但操作系统只能决定CPU的使用策略不能控制实际获得CPU执行权的程序。

线程执行有两种方式:

1.抢占式:

目前PC机中使用最多的一种方式,线程抢占CPU的执行权,当一个线程抢到CPU的资源后并不是一直执行到此线程执行结束,而是执行一个时间片后让出CPU资源,此时同其他线程再次抢占CPU资源获得执行权。

2.轮循式;

每个线程执行固定的时间片后让出CPU资源,以此循环执行每个线程执行相同的时间片后让出CPU资源交给下一个线程执行。

希望对您有所帮助!~

Java多线程的几种写法

有三种:

(1)继承Thread类,重写run函数

创建:

class xx extends Thread{

public void run(){

Thread.sleep(1000) //线程休眠1000毫秒,sleep使线程进入Block状态,并释放资源

}}

开启线程:

对象.start() //启动线程,run函数运行

(2)实现Runnable接口,重写run函数

开启线程:

Thread t = new Thread(对象) //创建线程对象

t.start()

(3)实现Callable接口,重写call函数

Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。

Callable和Runnable有几点不同:

①Callable规定的方法是call(),而Runnable规定的方法是run().

②Callable的任务执行后可返回值,而Runnable的任务是不能返回值的

③call()方法可抛出异常,而run()方法是不能抛出异常的。

④运行Callable任务可拿到一个Future对象,Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等

待计算的完成,并检索计算的结果.通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果

什么是JAVA的多线程?

一、 什么是多线程:

我们现在所使用操作系统都是多任务操作系统(早期使用的DOS操作系统为单任务操作系统),多任务操作指在同一时刻可以同时做多件事(可以同时执行多个程序)。

多进程:每个程序都是一个进程,在操作系统中可以同时执行多个程序,多进程的目的是为了有效的使用CPU资源,每开一个进程系统要为该进程分配相关的系统资源(内存资源)

多线程:线程是进程内部比进程更小的执行单元(执行流|程序片段),每个线程完成一个任务,每个进程内部包含了多个线程每个线程做自己的事情,在进程中的所有线程共享该进程的资源;

主线程:在进程中至少存在一个主线程,其他子线程都由主线程开启,主线程不一定在其他线程结束后结束,有可能在其他线程结束前结束。Java中的主线程是main线程,是Java的main函数;

二、 Java中实现多线程的方式:

继承Thread类来实现多线程:

当我们自定义的类继承Thread类后,该类就为一个线程类,该类为一个独立的执行单元,线程代码必须编写在run()方法中,run方法是由Thread类定义,我们自己写的线程类必须重写run方法。

run方法中定义的代码为线程代码,但run方法不能直接调用,如果直接调用并没有开启新的线程而是将run方法交给调用的线程执行

要开启新的线程需要调用Thread类的start()方法,该方法自动开启一个新的线程并自动执行run方法中的内容

结果:

java多线程的启动顺序不一定是线程执行的顺序,各个线程之间是抢占CPU资源执行的,所有有可能出现与启动顺序不一致的情况。

CPU的调用策略:

如何使用CPU资源是由操作系统来决定的,但操作系统只能决定CPU的使用策略不能控制实际获得CPU执行权的程序。

线程执行有两种方式:

1.抢占式:

目前PC机中使用最多的一种方式,线程抢占CPU的执行权,当一个线程抢到CPU的资源后并不是一直执行到此线程执行结束,而是执行一个时间片后让出CPU资源,此时同其他线程再次抢占CPU资源获得执行权。

2.轮循式;

每个线程执行固定的时间片后让出CPU资源,以此循环执行每个线程执行相同的时间片后让出CPU资源交给下一个线程执行。

希望对您有所帮助!~

如何使用Java编写多线程程序(1)

一、简介1、什么是线程要说线程,就必须先说说进程,进程就是程序的运行时的一个实例。线程呢可以看作单独地占有CPU时间来执行相应的代码的。对早期的计算机(如DOS)而言,线程既是进程,进程既是进程,因为她是单线程的。当然一个程序可以是多线程的,多线程的各个线程看上去像是并行地独自完成各自的工作,就像一台一台计算机上运行着多个处理机一样。在多处理机计算机上实现多线程时,它们确实可以并行工作,而且采用适当的分时策略可以大大提高程序运行的效率。但是二者还是有较大的不同的,线程是共享地址空间的,也就是说多线程可以同时读取相同的地址空间,并且利用这个空间进行交换数据。 2、为什么要使用线程为什么要使用多线程呢?学过《计算机体系结构》的人都知道。将顺序执行程序和采用多线程并行执行程序相比,效率是可以大大地提高的。比如,有五个线程thread1, thread2, thread3, thread4, thread5,所耗的CPU时间分别为4,5,1,2,7。(假设CPU轮换周期为4个CPU时间,而且线程之间是彼此独立的)顺序执行需要花费1Array个CPU时间,而并行需要的时间肯定少于1Array个CPU时间,至于具体多少时间要看那些线程是可以同时执行的。这是在非常小规模的情况下,要是面对大规模的进程之间的交互的话,效率可以表现得更高。 3、java中是如何实现多线程的与其他语言不一样的是,线程的观念在java是语言中是重要的,根深蒂固的,因为在java语言中的线程系统是java语言自建的, java中有专门的支持多线程的API库,所以你可以以最快的速度写一个支持线程的程序。在使用java创建线程的时候,你可以生成一个Thread类或者他的子类对象,并给这个对象发送start()消息(程序可以向任何一个派生自 Runnable 接口的类对象发送 start() 消息的),这样一来程序会一直执行,直到run返回为止,此时该线程就死掉了。在java语言中,线程有如下特点:§ 在一个程序中而言,主线程的执行位置就是main。而其他线程执行的位置,程序员是可以自定义的。值得注意的是对Applet也是一样。 § 每个线程执行其代码的方式都是一次顺序执行的。 § 一个线程执行其代码是与其他线程独立开来的。如果诸线程之间又相互协作的话,就必须采用一定的交互机制。 § 前面已经说过,线程是共享地址空间的,如果控制不当,这里很有可能出现死锁。 各线程之间是相互独立的,那么本地变量对一个线程而言就是完全独立,私有的。所以呢,线程执行时,每个线程都有各自的本地变量拷贝。对象变量(instance variable)在线程之间是可以共享的,这也就是为什么在java中共享数据对象是如此的好用,但是java线程不能够武断地访问对象变量:他们是需要访问数据对象的权限的。二、准备知识 在分析这个例子之前,然我们先看看关于线程的几个概念,上锁,信号量,和java所提供的API。 上锁对于大多数的程序而言,他们都需要线程之间相互的通讯来完成整个线程的生命周期,二实现线程之间同步的最简单的办法就是上锁。为了防止相互关联的两个线程之间错误地访问共享资源,线程需要在访问资源的时候上锁和解锁,对于锁而言,有读锁,写锁和读写锁等不同的同步策略。在java中,所有的对象都有锁;线程只需要使用synchronized关键字就可以获得锁。在任一时刻对于给定的类的实例,方法或同步的代码块只能被一个线程执行。这是因为代码在执行之前要求获得对象的锁。 信号量通常情况下,多个线程所访问为数不多的资源,那怎么控制呢?一个比较非常经典而起非常简单的办法就是采用信号量机制。信号量机制的含义就是定义一个信号量,也就是说能够提供的连接数;当有一个线程占用了一个连接时,信号量就减一;当一个线程是放了连接时,信号量就加一。

如何用Java编写多线程

在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。

对于直接继承Thread的类来说,代码大致框架是:

?

123456789101112 class 类名 extends Thread{ 方法1; 方法2; … public void run(){ // other code… } 属性1; 属性2; … }

先看一个简单的例子:

?

12345678910111213141516171819202122232425262728 /** * @author Rollen-Holt 继承Thread类,直接调用run方法 * */class hello extends Thread { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i 5; i++) { System.out.println(name + "运行 " + i); } } public static void main(String[] args) { hello h1=new hello("A"); hello h2=new hello("B"); h1.run(); h2.run(); } private String name; }

【运行结果】:

A运行 0

A运行 1

A运行 2

A运行 3

A运行 4

B运行 0

B运行 1

B运行 2

B运行 3

B运行 4

我们会发现这些都是顺序执行的,说明我们的调用方法不对,应该调用的是start()方法。

当我们把上面的主函数修改为如下所示的时候:

?

123456 public static void main(String[] args) { hello h1=new hello("A"); hello h2=new hello("B"); h1.start(); h2.start(); }

然后运行程序,输出的可能的结果如下:

A运行 0

B运行 0

B运行 1

B运行 2

B运行 3

B运行 4

A运行 1

A运行 2

A运行 3

A运行 4

因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的,呵呵。

注意:虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。

那么:为什么我们不能直接调用run()方法呢?

我的理解是:线程的运行需要本地操作系统的支持。

如果你查看start的源代码的时候,会发现:

?

1234567891011121314151617 public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } private native void start0();

注意我用红色加粗的那一条语句,说明此处调用的是start0()。并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。

但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。

通过实现Runnable接口:

大致框架是:

?

123456789101112 class 类名 implements Runnable{ 方法1; 方法2; … public void run(){ // other code… } 属性1; 属性2; … }

来先看一个小例子吧:

?

123456789101112131415161718192021222324252627282930 /** * @author Rollen-Holt 实现Runnable接口 * */class hello implements Runnable { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i 5; i++) { System.out.println(name + "运行 " + i); } } public static void main(String[] args) { hello h1=new hello("线程A"); Thread demo= new Thread(h1); hello h2=new hello("线程B"); Thread demo1=new Thread(h2); demo.start(); demo1.start(); } private String name; }

【可能的运行结果】:

线程A运行 0

线程B运行 0

线程B运行 1

线程B运行 2

线程B运行 3

线程B运行 4

线程A运行 1

线程A运行 2

线程A运行 3

线程A运行 4

关于选择继承Thread还是实现Runnable接口?

其实Thread也是实现Runnable接口的:

?

12345678 class Thread implements Runnable { //… public void run() { if (target != null) { target.run(); } } }

其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有,Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。关于代理模式,我曾经写过一个小例子呵呵,大家有兴趣的话可以看一下:

Thread和Runnable的区别:

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

?

1234567891011121314151617181920212223 /** * @author Rollen-Holt 继承Thread类,不能资源共享 * */class hello extends Thread { public void run() { for (int i = 0; i 7; i++) { if (count 0) { System.out.println("count= " + count--); } } } public static void main(String[] args) { hello h1 = new hello(); hello h2 = new hello(); hello h3 = new hello(); h1.start(); h2.start(); h3.start(); } private int count = 5; }

【运行结果】:

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。

我们换为Runnable接口:

?

12345678910111213141516171819 /** * @author Rollen-Holt 继承Thread类,不能资源共享 * */class hello implements Runnable { public void run() { for (int i = 0; i 7; i++) { if (count 0) { System.out.println("count= " + count--); } } } public static void main(String[] args) { hello he=new hello(); new Thread(he).start(); } private int count = 5; }

【运行结果】:

count= 5

count= 4

count= 3

count= 2

count= 1

总结一下吧:

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

所以,本人建议大家劲量实现接口。

?

什么是Java多线程

多线程的概念?

说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程。

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

进程可以简单的理解为一个可以独立运行的程序单位。它是线程的集合,进程就是有一个或多个线程构成的,每一个线程都是进程中的一条执行路径。

那么多线程就很容易理解:多线程就是指一个进程中同时有多个执行路径(线程)正在执行。

为什么要使用多线程?

1.在一个程序中,有很多的操作是非常耗时的,如数据库读写操作,IO操作等,如果使用单线程,那么程序就必须等待这些操作执行完成之后才能执行其他操作。使用多线程,可以在将耗时任务放在后台继续执行的同时,同时执行其他操作。

2.可以提高程序的效率。

3.在一些等待的任务上,如用户输入,文件读取等,多线程就非常有用了。

缺点:

1.使用太多线程,是很耗系统资源,因为线程需要开辟内存。更多线程需要更多内存。

2.影响系统性能,因为操作系统需要在线程之间来回切换。

3.需要考虑线程操作对程序的影响,如线程挂起,中止等操作对程序的影响。

4.线程使用不当会发生很多问题。

总结:多线程是异步的,但这不代表多线程真的是几个线程是在同时进行,实际上是系统不断地在各个线程之间来回的切换(因为系统切换的速度非常的快,所以给我们在同时运行的错觉)。

2.多线程与高并发的联系。

高并发:高并发指的是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……。

而多线程只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。

多线程在高并发问题中的作用就是充分利用计算机资源,使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。

3.线程的创建,停止,常用方法介绍。

1.线程的创建:

线程创建主要有2种方式,一种是继承Thread类,重写run方法即可;(Thread类实现了Runable接口)

另一种则是实现Runable接口,也需要重写run方法。

线程的启动,调用start()方法即可。 我们也可以直接使用线程对象的run方法,不过直接使用,run方法就只是一个普通的方法了。

其他的还有: 通过匿名内部类的方法创建;实现Callable接口。。。。。

2.线程常用方法:

currentThread()方法:该方法返回当前线程的信息 .getName()可以返回线程名称。

isAlive()方法:该方法判断当前线程是否处于活动状态。

sleep()方法:该方法是让“当前正在执行的线程“休眠指定的时间,正在执行的线程是指this.currentThread()返回的线程。

getId()方法:该方法是获取线程的唯一标识。

3.线程的停止:

在java中,停止线程并不简单,不想for。。break那样说停就停,需要一定的技巧。

线程的停止有3种方法:

1.线程正常终止,即run()方法运行结束正常停止。

2.使用interrupt方法中断线程。

3.使用stop方法暴力停止线程。

interrupt方法中断线程介绍:

interrupt方法其实并不是直接中断线程,只是给线程添加一个中断标志。

判断线程是否是停止状态:

this.interrupted(); 判断当前线程是否已经中断。(判断的是这个方法所在的代码对应的线程,而不是调用对象对应的线程)

this.isInterrupted(); 判断线程是否已经中断。(谁调用,判断谁)

注:.interrupted()与isInterrupted()的区别:

interrupted()方法判断的是所在代码对应的线程是否中断,而后者判断的是调用对象对应的线程是否停止

前者执行后有清除状态的功能(如连续调用两次时,第一次返回true,则第二次会返回false)

后者没有清除状态的功能(两次返回都为true)

真正停止线程的方法:

异常法:

在run方法中 使用 this.interrupted();判断线程终止状态,如果为true则 throw new interruptedException()然后捕获该异常即可停止线程。

return停止线程:

在run方法中 使用 this.interrupted();判断线程终止状态,如果为true则return停止线程。 (建议使用异常法停止线程,因为还可以在catch中使线程向上抛,让线程停止的事件得以传播)。

暴力法:

使用stop()方法强行停止线程(强烈不建议使用,会造成很多不可预估的后果,已经被标记为过时)

(使用stop方法会抛出 java.lang.ThreadDeath 异常,并且stop方法会释放锁,很容易造成数据不一致)

注:在休眠中停止线程:

在sleep状态下停止线程 会报异常,并且会清除线程状态值为false;

先停止后sleep,同样会报异常 sleep interrupted;

4.守护线程。

希望对您有所帮助!~

java多线程写的的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于Java 多线程编程、java多线程写的的信息别忘了在本站进行查找喔。

The End

发布于:2022-11-30,除非注明,否则均为首码项目网原创文章,转载请注明出处。