`
Strive_sprint
  • 浏览: 22495 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

java多线程初步理解

 
阅读更多

 

      也许我们经常做的事就是一边聊QQ一边听音乐,有的还一边玩游戏,这一切都是多任务实现的。而java语言使用多线程实现了一个程序中的多个任务同时运行。

      那到底是不是同时执行多线程呢?显然不是,CPU一次只能然一个线程执行,由于线程之间切换速度很快,所以在我们看来是同时执行的。

 

java中如何实现多线程:

      1.继承Thread类创建多线程。

      2.实现Runnable接口创建多线程。

 

      继承Thread类,重写run()方法是实现多线程的方式之一,Thread类本身就实现了Runnable接口。

如下例继承Thread类:

public class ThreadTest extends Thread{
	public void run(){
		while(true){
			String name = Thread.currentThread().getName();
			sayHello(name);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	public void sayHello(String name){
		System.out.println(name+"说hello");
	}
	public static void main(String [] agrs){
		ThreadTest tt1 = new ThreadTest();
		ThreadTest tt2 = new ThreadTest();
		tt1.start();
		tt2.start();
	}
}

 

我的运行结果(每个人的运行结果都会不同):

Thread-0说hello
Thread-1说hello
Thread-1说hello
Thread-0说hello
Thread-1说hello
Thread-0说hello
Thread-1说hello
Thread-0说hello

 

      可以看出线程是一个一个执行的,并且不是按顺序执行的,红色标记的地方说明。cpu为每个线程分配了时间片,哪个线程得到了CPU,哪个线程就得到执行,这个在后面再说明。

 

      实现Runnable接口,实现run()方法来创建多线程,如下例:

public class ThreadTest implements Runnable{
	public void run() {
		while(true){
			String name = Thread.currentThread().getName();
			sayHello(name);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	public void sayHello(String name){
		System.out.println(name+"说hello");
	}
	public static void main(String [] agrs){
		Runnable r = new ThreadTest();
		Thread thread1 = new Thread(r);
		Thread thread2 = new Thread(r);
		thread1.start();
		thread2.start();
	}
}

      这里只是创建线程对象有稍微的区别。

 

      那么他们之间有什么区别?甚至有的人问哪个更好?因为我就这么问过,但是在网上找到的答案基本都很片面,只找到了一个说的比较好,还需要时间研究研究。我列出来大家看看:

      1.适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想。

      2.可以避免由于java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。

      3.有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程可以操作相同的数据,与它们的代码无关。当共享访问相同的对象时,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例

 

      那么实现多线程都是对run()方法重写,为什么不是直接调用run()方法而是调用start()方法呢?这里我们来看看run()和start()方法的区别。

start():

      通过调用start()方法来启动线程,此时线程处于就绪状态,一旦得到CPU时间片就执行run()方法,方法run()称为线程体,它包含了要执行这个线程的内容,当run()方法运行结束,线程随即终止。

run():

      run()方法只是Thread类的一个普通方法,如果直接调用run()方法,程序中只有主线程这一个线程,执行路径只有一条,要这个方法执行完才能执行下面的代码,这就没达到多线程的目的。

 

继续看如上例子,如果是:

      thread1.run();
         thread2.run();

那么运行结果为:

main说hello
main说hello
main说hello
main说hello
main说hello
main说hello
main说hello

 

      main就是我们一直以来接触的程序的入口(主方法),其实它本身就是一个线程,并且是主线程。 

 

线程的生命周期

      线程具有生命周期,包含3个状态,使用线程实例调用start()方法之前,线程处于出生状态,当调用start()方法后,线程就处于就绪状态,当线程得到系统资源后进入运行状态,当时间片结束线程又回到就绪状态,继续等待资源。

 

      而在线程执行过程中,线程又可能转入等待,睡眠,阻塞或者死亡状态

 

      1.线程在执行过程中调用wait()方法进入等待状态,这时线程释放持有的资源,必须采用notify()或者notifyAll()方法来唤醒该进程或者被别的对象调用interrupt()方法打断,这个方法会抛出一个InterruptedException异常,这个异常如果不捕获处理,线程就会异常终止,当线程被唤醒后,再次进入就绪状态,等待资源。

      2.线程在执行过程中调用sleep()方法,进入睡眠状态,这个过程线程不会释放持有的资源,待睡眠时间完后即进入就绪状态,不会立即进入执行状态,因为线程调度机制恢复线程的运行也需要时间。当然睡眠状态也会被interrupt(0方法打断,效果和wait()一样。

      3.线程执行过程中,因为某些原因而使其停止执行。当线程阻塞后,别的贤臣就有机会执行,当线程阻塞被解除后进入就绪状态,等待被调度。

       阻塞原因有:

        a.线程调用sleep()方法放弃CPU时间片。

        b.线程调用wait()方法,等待别的线程来唤醒它。

        c.线程调用阻塞IO方法,方法返回前处于阻塞状态。(IO后面会分析)

        d.线程执行需要资源,在执行过程中,某些资源被别的线程持有,则该线程会处于阻塞状态来等待资源的获取。

        e.程序调用suspend()方法将该线程挂起,该方法容易产生死锁。

      4.线程进入死亡状态也是有原因的。

       死亡原因:

        a.线程执行完run()方法进入死亡状态。

        b.线程通过某种方式终止线程使其进入死亡状态(接下来分析)。

        c.线程抛出未捕获的线程使线程异常终止。

 

终止线程

      在早期的JDK中提供了stop()方法来终止线程,但是新版本不建议使用,提倡用布尔标记控制循环的停止来达到终止线程的目的。

      1.在循环体中,通过条件判断,符合条件的就break;跳出循环,终止线程。

      2.循环条件不要写成true,而是手动控制循环条件的false来达到终止线程的目的。

 

线程的调度

      1.线程执行前,通过优先级来达到线程调度的目的,优先级高的线程优先得到CPU执行。线程的优先级可以在程序中表明该线程的重要级,学过操作系统的都明白有很多的调度算法,这里不细说了。

      2.线程执行过程中,可以通过join()方法来调度线程,比如:

threadA = new Thread(new Runnable(){
	public void run() {
		for(int i = 0;i<=100;i++){
			if(i >= 50){
				threadB.join();
			}
		}
	}
});

      显然在线程A执行时,当i=50的时候,就会执行线程B,直到线程B执行完,线程A才会继续执行,这样也能达到线程调度的目的。

 

线程安全

      在多线程中,说到什么最重要,要属线程安全当之无愧,引入多线程的目的就是对大量任务进行有序的管理,通过多个任务混合使用,可以更有效的利用计算机的资源

      使用多线程,会发生两个以上的线程抢占资源的问题,必须防止资源访问的冲突。java提供线程同步机制可以防止资源访问的冲突(下篇分析)。

 

      欲知后事如何,请看下集。。。

分享到:
评论

相关推荐

    Java多线程文章系列.pdf

    #### 三、Java多线程程序设计初步 ##### 1. 线程的创建 - **继承Thread类**: - 重写`run()`方法。 - **实现Runnable接口**: - 实现`run()`方法。 - 将`Runnable`对象传递给`Thread`构造函数。 ##### 2. 线程的...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │ 高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │ 高并发编程第一阶段07讲、策略模式在Thread和Runnable...

    [JWFD开源工作流]JAVA单线程时钟算法和代码(初步设计)

    4. **线程同步机制**:如`synchronized`关键字或`Lock`对象,保证多线程环境下的数据一致性,防止并发问题。 5. **异常处理**:确保即使在出现异常的情况下,时钟仍然能够正常运行,避免程序崩溃。 从代码实现的...

    blockGame 多线程 图形界面 背景图背景音乐 java实例 小游戏

    尽管文件大小限制没有包含图片和音乐资源,我们依旧可以通过这个项目学习到如何利用Java实现一个多线程、具有图形界面的游戏。 在Java中,多线程技术是实现blockGame游戏逻辑的关键。通过多线程,程序可以同时执行...

    多线程游戏-snake贪吃蛇

    在Java编程语言中实现贪吃蛇游戏,我们会涉及多线程技术,这是理解并发处理和提升程序性能的关键概念。下面我们将详细探讨如何使用Java实现一个多线程的Snake游戏。 首先,贪吃蛇游戏的核心是蛇的移动和食物的生成...

    Java游戏编程初步

    总的来说,Java游戏编程初步会引导初学者理解Applets的开发流程、线程的概念及其在游戏中的应用,为进一步深入Java游戏开发打下基础。虽然这个领域可能需要更多的学习,如图形库、物理引擎和网络编程,但这个起点为...

    JAVA初步学习课件

    在学习过程中,应着重理解每个概念的实际应用场景,例如如何通过类和对象来抽象现实世界的问题,如何使用异常处理来增强程序的健壮性,以及如何利用多线程提升程序效率。同时,不断通过做题和编写小程序来锻炼解决...

    多线程起步,总结的,一些方法的使用,简单的列子,使用方法

    本文将深入探讨多线程的基础知识,包括它的概念、使用场景、核心方法以及通过简单示例来帮助初学者理解多线程的实践操作。 1. 多线程概念: 多线程是指在一个应用程序中同时执行多个独立的执行路径,每个路径称为一...

    龟兔赛跑——Java程序设计课程多线程部分教学设计.pdf

    通过龟兔赛跑的例子,学生已经初步了解了多线程的概念及编程方法。此时可以进一步提出思考题,例如如果乌龟和兔子在赛跑过程中需要吃东西 怎么办?如果乌龟和兔子都要吃同一个篮子里面 的食物怎么办?这时可以引入...

    java语言结构初步

    11. **多线程**:Java内置对多线程的支持,通过Thread类或实现Runnable接口可以创建并管理线程。 学习Java语言结构的过程中,不仅需要理解和掌握这些知识点,还要通过编写实际的代码来加深印象,不断实践和调试。配...

    初步了解java编程语言

    - Java内置对多线程的支持,可以通过实现Runnable接口或继承Thread类创建线程。 - 线程同步机制包括synchronized关键字、wait(), notify(), notifyAll()方法以及Lock接口。 8. **网络编程**: - Java提供了...

    java游戏编程初步

    Java内置了对多线程的支持,允许开发者轻松创建和控制线程,这对于处理复杂的动画、游戏逻辑和用户输入非常有用。 - **Thread类**:是Java中表示线程的实体,可以通过继承`Thread`类并重写`run()`方法来自定义线程...

    Java线程从入门到实践.doc

    通过以上内容的学习,可以初步掌握Java多线程的基本概念和操作。然而,实际应用中还需要考虑线程优先级、线程池、线程通信、线程中断、异常处理等多个方面,这些都是Java线程编程的重要组成部分。在实践中不断探索和...

    java初步学习指导

    10. **多线程编程**: - 学习如何创建和管理线程,理解同步和互斥,使用 synchronized 关键字和 volatile 属性。 11. **网络编程**: - 理解套接字(Socket)编程,学会创建客户端和服务端的通信。 12. **Java ...

    java教程初步讲解

    3. **类与对象**:Java是面向对象的编程语言,理解类的概念、对象的创建与销毁、封装、继承和多态性等核心概念。 4. **方法与函数**:学习如何定义和调用方法,了解参数传递机制,以及静态与非静态方法的区别。 二...

    华育国际java初步课间及课上练习

    9. **多线程**:理解线程的概念,创建和控制线程,以及同步机制(如`synchronized`关键字和`wait()`,`notify()`方法)。 10. ** Swing GUI编程**:如果课程深入,可能会接触到图形用户界面的设计,如使用`JFrame`...

    Accp6.0 S1 JAVA 理解程序逻辑 第1章

    有了这些基础知识,学员将能够逐步构建更复杂的程序,并为进一步深入学习Java的高级特性,如面向对象编程、类库的使用、多线程以及数据库连接等做好准备。因此,对于希望投身IT行业的初学者而言,这是一个不可或缺的...

Global site tag (gtag.js) - Google Analytics