多线程的前世今生

本文详细介绍了多线程的概念,包括进程与线程的区别,以及如何在Java中创建和管理线程。重点讨论了线程安全、同步机制、线程间通信以及如何优雅地停止线程,对于多线程编程提供了实用的指导。
摘要由CSDN通过智能技术生成

一、多线程概述

1、进程:操作系统中同时运行的程序

是一个正在执行的程序。
每一个进程执行都有一个执行顺序。该顺序是一个执行路径。
或者叫一个控制单元。
每个进程都有自己独立的一块内存空间,一个进程中可以有多个线程。

2、线程:在同一个进程中同时运行的任务

就是进程中的一个独立的(执行任务)控制单元。
线程在控制着进程的执行。
一个进程中至少有一个线程。多个线程可以共享数据。如:多线程下载软件
Java VM启动的时候会有一个进程java.exe。
该进程中至少一个线程负责java程序的执行。
而且这个线程运行的代码存在于main方法中。
该线程称为主线程

3、扩展

其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。

4、线程与进程的比较

线程具有许多传统进程所具有的特征,故又称为轻型线程(Light-Weight Process)或进程元;而把传统的进程称为重型进程(Heavy-Weight Process),它相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进程都有若干个线程,至少需要一个线程。

进程与线程的区别:

1)进程有独立的进程空间,进程中的数据存放空间(堆空间和栈空间)是独立的。

2)线程的堆空间是共享的,栈空间是独立的,现场称消耗的资源也比进程小,相互之间可以影响的。

二、创建线程

1、如何在自定义的代码中,自定义一个线程呢?

通过对API的查找,java已经提供䠾对线程的这类事物的描述,就
Thread类,创建线程的第一种方式,继承Thread类。
步骤:
a.定义继承Thread。
b.复写Thread类中的run方法。
目的:将自定义代码存储在run方法,让线程运行。
c.调用线程的start方法,该方法有两个作用:启动线程和调用run方法。

2、随机性

当多线程程序运行时,发现运行结果每一次都不同。
因为多个线程都获取cpu的执行权,cpu执行到谁,谁就执行。
明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)
cpu在做着快速的切换,以达到看上去是同时运行的效果。
我们可以形象地把多线程的运行行为视为在互相抢夺cpu的执行权。
这就是多线程的特性:随机性。谁抢到谁执行,至于执行多长,cpu说了算。

3、为什么要覆盖run方法呢?

Thread类用于描述线程。
该类就定义了一个功能,用于存储线程要运行的代码。
例1
class Demo extends Thread//继承线程,覆盖run方法
{
	public void run()
	{
		for (int x=0;x<60 ;x++ )//创建个循环打印看效果
		{
			System.out.println("demo run-----"+x);
		}
	}
}

class ThreadDemo
{
	public static void main(String[] args)
	{
		Demo d=new Demo();//创建好一个线程
		//d.start();//开启线程并执行该线程的run方法
		d.run();//仅仅是对象调用方法,而线程创建了,并没有运行。

		for (int x=0;x<60 ;x++ )//创建个循环打印看效果
		{
			System.out.println("Hello world---"+x);
		}
	}
}
小练习:
/*
需求:创建两个线程和主程序交替运行
思路:1.创建一个类继承线程,
	  2.主函数中开启两条线程
*/

class Test extends Thread//Test继承线程
{
	private String name;
	Test(String name)//创建名字方法比较好分别出来
	{
		this.name=name;
	}
	public void run()//覆盖父类run方法
	{
		for (int x=0;x<60 ;x++ )
		{
			System.out.println(name+"run---"+x);
		}
		
	}
}

class TestDemo
{
	public static void main(String[] args)
	{
		Test t1=new Test("one");//创建第一条线程
		Test t2=new Test("two");//创建第二条线程
		t1.start();//开启线程,运行run方法
		t2.start();//开启线程,运行run方法
		
		for (int x=0;x<60 ;x++ )
		{
			System.out.println("main"+x);
		}
		
	}
}
结果输出:

4、线程运行状态

5、获取线程对象及名称

线程都有自己的名称
Thread-编号 该编号从0开始。
局部的变量在每一个线程中都有一份。
statiic Thread current Thread( );获取当前线程对象。
getName();获取线程名称
设置线程名称:setName或者构造函数。

6、创建线程的第二种方式

实现从Runnable接口
步骤:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法。
将要运行的代码存放在该run方法中。
3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
       为什么要将Runnable接口的子类对象传递给Thread的构造函数。
        因为,自定义的run方法所属的对象时Runnable接口的子类对象。
所以要让线程去指定指定对象的run方法,就必须明确该run方法所属对象。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
例1
思路:1.定义类实现接口Runnable
	  2.存放要运行的代码在run方法中,覆盖Runnable中的run方法
	  3.在主函数中建立线程对象
	  4.将Runable的子类对象作为实际参数传递给Thread
	  5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
*/

class Ticket implements Runnable//实现Runnable接口
{
	private
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值