java之线程

一、线程的基本概念

线程是一个程序内部的顺序控制流

线程和进程的区别:

  • 每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销。
  • 线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的空间小。
  • 多进程:在操作系统中能同时运行多个任务(程序)。
  • 多线程:在同一应用程序中有多个顺序流同时执行。

进程是一个静态的概念,平时说的进程的执行指的是进程中main方法开始执行了。在机器中实际上运行的都是线程。

java中的线程:

  • java的线程是通过java.lang.Thread类来实现的
  • jvm启动时会有一个由public static void main(){ } 所定义的线程。
  • 可以通过创建Thread的实例来创建新的线程。
  • 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。
  • 通过调用Thread类的 start()方法来启动一个线程。

二、线程的创建和启动

1、第一种: 定义线程类实现Runnable接口

  • Thread myThread = new Thread(Target)// Target 为Runnable 接口类型。
    (在这也有多态的存在,父类的引用指向子类的对象。)

  • Runnable 中只有一个方法
    - public void run();用以定义线程运行体。

  • 使用Runnable 接口可以为多个线程提供共享的数据

  • 在实现Runnable接口的类的run方法定义中可以使用Thread的静态方法。
    -public static Thraed currentThread()获取当前线程的引用。

2、第二种:

可以定义一个Thread的子类并重写其run()方法。

class myThread extends Thread{
public void run {
}
}

  • 然后生成该类的对象
    - myThread mythread = new myThread (…)

Thread类本身实现了Runnable接口。

代码示例:

public class TestThread1 {
	public static void main(String args[]) {
		Runner1 r = new Runner1();
		//在此main方法产生一个分支执行,执行Runner1 中的run方法。而main方法继续执行
		Thread  r1 = new Thread(r);
		Thread  r2 = new Thread(r);		
		//r1.run();   这相当于方法调用,调用Runner1中的run方法。
		//线程启动,线程启动必须调用Thread类的的start方法。
		r1.start();
		//用第二种方法时不用创建Thread对象,因为本身就是Thread的子类了,所以直接调用start方法。
		//r2.start();
		for(int i=9;i>=0;i--) {
			System.out.println("Main thread"+i+" ");
		}

	}
}

 //方法2、定义Thread类的子类。class Runner1 extends Thread {
 //方法1、实现Runnable接口
class Runner1 implements Runnable {
	public void run (){
		for(int i=0;i<10;i++) {
			System.out.println("The Runner1 "+i+" ");
		}
	}
}

运行结果:

Main thread9
The Runner1 0
Main thread8
The Runner1 1
The Runner1 2
The Runner1 3
Main thread7
Main thread6
The Runner1 4
The Runner1 5
The Runner1 6
The Runner1 7
Main thread5
The Runner1 8
Main thread4
The Runner1 9
Main thread3
Main thread2
Main thread1
Main thread0

因为cpu分配的时间片不一样,所以是交换运行的。
Runnable接口应由任何类实现,其实例将由线程执行。 该类必须定义一个无参数的方法,称为run 。

由于继承比较死板,无法再从其他类继承,所以建议使用第一种方法(实现Runnable接口)来创建线程。

实现Runnable接口更好的理由

解耦角度:Runnable接口只定义了一个抽象方法run,语义非常明确,就是线程需要执行的任务。而Thread类除了线程需要执行的任务,还需要维护线程的生命周期、状态转换等

资源角度:继承Thread类的方式,如果想要执行一个任务,必须新建一个线程,执行完成后还要销毁,开销非常大;而实现Runnable接口只需要新建任务,可以做到同一个线程执行多个任务,大大减小了线程创建、销毁的资源浪费

扩展角度:Java不支持多继承,一个类如果继承了Thread类就不能再继承别的类,不利于未来的扩展

三、线程状态转换

在这,没有操作系统里的复杂,简单了解一下即可。

在这里插入图片描述

创建之后得启动表示准备好进入cpu了,但由于cpu正在执行任务或拥挤,所以准备好之后还得排队,cpu给时间片可以进入运行状态开始运行,若运行期间时间片到头或没有资源则又会进入就绪状态排队等待…

线程控制的基本方法:

isAlive():判断线程是否终止。

getPriority():获得线程的优先级数值。

setPriority():设置线程的优先级数值。

Thread.sleep():将当前线程睡眠 指定时间毫秒数

join():调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。

yield():让出cpu,使当前线程进入就绪状态等待调度。

wait(): 当前线程进入对象的 wait pool

notify()/ notifyAll():唤醒对象wait pool 中的一个 / 所有 等待的线程。

sleep()、

sleep方法
public static void sleep (long millis,int nanos) throws InterruptedException

注* 静态方法可以由类名直接调用

导致正在执行的线程以指定的毫秒数加上指定的纳秒数来暂停(临时停止执行),这取决于系统定时器和调度器的精度和准确性。 线程不会丢失任何显示器的所有权。
参数
millis - 以毫秒为单位的睡眠时间长度
nanos - 0-999999额外的纳秒睡眠

public class TestThread2 {
	public static void main(String ages[]) {
		Runner2 r = new Runner2();
		Thread r1 = new Thread(r);
		r1.start();
	}
}
 class Runner2 implements Runnable {
	 public void run() {
		 for(int i=0;i<30;i++) {
			 if(i%10==0 && i!=0) {
				 try {
				 Thread.sleep(10000);//睡眠10秒
				 System.out.println();
			 }catch(InterruptedException e) {
				 e.printStackTrace();
			 }
			 }
			 System.out.println("No.:"+i);
		 }
	 }
 }

每个10打印10个数。
运行结果(部分):

No.:0
No.:1
No.:2
No.:3
No.:4
No.:5
No.:6
No.:7
No.:8
No.:9

No.:10
No.:11
No.:12
No.:13
No.:14
No.:15
No.:16
No.:17
No.:18
No.:19

线程的优先级别

java提供一个线程调度器来监控程序中启动后将入就绪状态的所有线程。
线程调度器按照线程的优先级决定应该调度哪一个线程来执行。
线程的优先级用数字来表示,范围从1~10,一个线程的缺省优先级为5.
优先级高的得到的cpu执行的时间片就会越多。

举例说明:

public class TestPriority {
	public static void main(String[] args) {
		Thread t1 = new Thread(new T1());
		Thread t2 = new Thread(new T2());
		//不设置优先级的话,运行结果t1、t2执行的时间差不多,交换执行
		t1.setPriority(Thread.NORM_PRIORITY + 3);//提高t1的优先级,t1的时间片多与t2
		t1.start();
		t2.start();
	}
}
class T1 implements Runnable {
	public void run() {
		for(int i=0; i<1000; i++) {
			System.out.println("T1: " + i);
		}
	}
}
class T2 implements Runnable {
	public void run() {
		for(int i=0; i<1000; i++) {
			System.out.println("------T2: " + i);
		}
	}
}

设置优先级之后、部分运行结果截图:
在这里插入图片描述

可以看出t1的执行时间多于t2。

四、线程同步

未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值