java学习笔记-----多线程

2022-08-02,,

多线程

1.继承Thread类

Thread类是在java.lang包中定义的,一个类只要继承了Thread类,就成为多线程,而且必须覆写run方法,此方法为线程的主体。而如果要正确的启动线程,不能直接调用run()方法,而应该调用Thread类中继承过来的start方法
[使用格式]
class 类名称 extends Thread{
属性;
方法;
public void run(){
线程主体;
}
}
案例

package org.sz.demo07.threaddemo;
class MyThread extends Thread{
	private String name;
	public MyThread(String name) {
		this.name =name;
	}
	public void run() {
		for(int i = 0; i < 10; i++ ) {
			System.out.println(name + "运行 , i ="  + i);
		}
	}
}
public class ThreadDemo01{
	public static void main(String args[]) {
		MyThread mt1 = new MyThread("线程 a");
		MyThread mt2 = new MyThread("线程 b");
		mt1.start();
		mt2.start();
	}
}

因为哪个线程对象抢到了cpu资源,哪个线程就可以运行,所以每次运行的结果肯定是不一样的

2.Runnable接口

在java中也可以通过实现Runnable接口来实现多线程,Runnable接口中只定义了一个抽象方法;
public void run();
【使用格式】
class 类名称 implements Runnable{
属性;
方法;
public void fun(){
线程主体;
}

}

  • 使用Runnable接口的优点
  • 适合多个相同程序代码的线程去处理同一个资源;
  • 可以避免由于单继承局限所带来的影响;
  • 增加了程序的健壮性,代码能够被多个线程所分享,代码与数据是独立的人
    案例:
class MyThread implements Runnable {
	private String name;
	public MyThread(String name) {
		this.name = name;
	}
	public void run() {
		for(int i =0; i < 10; i ++) {
			System.out.println(name +"运行" +i);
		}
	}
};
public class RunnableDemo01{
	public static void main(String args[]) {
		MyThread mt1 = new MyThread("线程 a ");
		MyThread mt2 = new MyThread("线程 b ");
		Thread t1 = new Thread (mt1);
		Thread t2 = new Thread (mt2);
		t1.start();
		t2.start();
	}
}

*Thread 类是Runnable类的子类

  • 如果一个类继承了Thread类,则不适合多个线程共享资源,而实现了Runnable接口,就可以利用 synchronized(this)方便地实现资源的共享;
  • 案例 Thread不能资源共享
class MyThread extends Thread{
	private int ticket = 5;
	
	public void run() {
		for(int i = 0; i < 100; i++ ) {
			if(ticket>0) {
			System.out.println("卖票: ticket = " + ticket--);
			}
		}
	}
}
public class ThreadDemo02{
	public static void main(String args[]) {
		MyThread mt1 = new MyThread();
		MyThread mt2 = new MyThread();
		MyThread mt3 = new MyThread();
		mt1.start();
		mt2.start();
		mt3.start();
	}
}

  • Runnable 接口 资源共享
class MyThread implements Runnable {
	private int ticket = 5;
	public void run() {
		for(int i =0; i < 100; i ++) {
			synchronized(this)	{		//设置需要同步的操作
			if(ticket > 0) {
			System.out.println("卖票:ticket =" +ticket --);
			}
		}
	}
}
};
public class RunnableDemo02{
	public static void main(String args[]) {
		MyThread mt = new MyThread();
		new Thread(mt).start();
		new Thread(mt).start();
		new Thread(mt).start();
		
	}
}

3.同步方法

使用synchronized关键字将一个方法声明成同步方法

  • 案例
class MyThread implements Runnable {
	private int ticket = 5;
	public synchronized  void run() {
		for(int i =0; i < 100; i ++) {
				
			if(ticket > 0) {
			System.out.println("卖票:ticket =" +ticket --);
		
		}
	}
}
};
public class RunnableDemo03{
	public static void main(String args[]) {
		MyThread mt = new MyThread();
		new Thread(mt).start();
		new Thread(mt).start();
		new Thread(mt).start();
		
	}
}

4.线程的状态

  • 创建状态 :准备好了一个多线程的对象; Thread t = new Thread()
  • 就绪状态:调用了start()方法,等待cpu进行调度
  • 运行状态,执行run()方法
    阻塞状态:暂时停止执行,可能将资源交给其他线程使用
  • 终止状态:线程停止使用
  • 实际上线程调用start方法时不是立刻启用,而是等待cpu进行调度;

5.线程操作的主要方法

a.取得线程名称

  • 线程的名字在线程启动之前设置,避免重名
class MyThread implements Runnable {
	public void run() {
		for(int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName()+ "运行 ,i = " + i);
		}
	}
}

public class ThreadNameDemo{
	public static void main(String args[]) {
		MyThread mt = new MyThread();
		new Thread(mt).start();		//系统自动设置线程名称
		new Thread(mt,"线程——a").start();		//	手动设置线程名称
		new Thread(mt,"线程——b").start();		//	手动设置线程名称
		new Thread(mt).start();	
		new Thread(mt).start();	
		
		
		
	}
}

b.取得当前的线程名称

class MyThread implements Runnable {
	public void run() {
		for(int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName()+ "运行 ,i = " + i);
		}
	}
}

public class CurrentThreadDemo{
	public static void main(String args[]) {
		MyThread mt = new MyThread();
		new Thread(mt,"线程").start();		//	启动线程
		mt.run();	
	}
}

  • 主方法也是一个线程
  • 在java运行时至少启动了2个线程,启动时,会启动一个JVM,每个JVM实际上就是在操作系统中启动了一个进程,java中本身具备了垃圾收集机制

c.判断线程是否启动

class MyThread implements Runnable {
	public void run() {
		for(int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName()+ "运行 ,i = " + i);
		}
	}
}

public class ThreadAlivaDemo{
	public static void main(String args[]) {
		MyThread mt = new MyThread();
		Thread t = new Thread(mt,"编程");
		System.out.println("线程开始执行之后-->" + t.isAlive());
		t.start();
		System.out.println("线程开始执行之后-->" + t.isAlive());
		for(int i = 0; i< 3; i++ )
		{
			System.out.println(" main 运行 -->" + i);
		}
		System.out.println("线程开始执行之后-->" + t.isAlive());
		}
};

d.线程的强制运行

  • 之后的输出全部由一个线程完成,主线程必须等待这个线程完成之后才会继续执行;使用join方法
class MyThread implements Runnable{
	public void run() {
		for(int i = 0; i < 50;i ++ ){
			System.out.println(Thread.currentThread().getName()  + "运行, i=" +i);
		}
	}
};
public class ThreadJoinDemo{
	public static void main(String main[]) {
		MyThread mt1 = new MyThread ();
		Thread t = new Thread (mt1,"线程");
		t.start();
		for(int i = 0; i < 50; i++) {
			if(i>10) {
				try {
					t.join();
				}catch (InterruptedException e) {}
				
			}
			System.out.println("Main线程运行-->" + i);
		}
		System.out.println("代码运行之后-->" + t.isAlive());
	}
}

e.线程的休眠

  • 允许一个线程进行短暂的休眠,直接使用Thread.sleep()方法即可实现休眠
class MyThread implements Runnable{
	public void run() {
		for(int i = 0; i < 50;i ++ ){
			try{
				Thread.sleep(500);
			}catch(Exception e) {}
			System.out.println(Thread.currentThread().getName()  + "运行, i=" +i);
		}
	}
};
public class ThreadSleepDemo{
	public static void main(String main[]) {
		MyThread mt1 = new MyThread ();
		Thread t = new Thread (mt1,"线程");
		t.start();
		
	}
}

f.线程的中断

  • 中断线程的休眠,使用interrupt()方法
class MyThread implements Runnable{
	public void run() {
		System.out.println("1.进入run()方法");
			try{
				Thread.sleep(10000);
				System.out.println("2.完成休眠");
			}catch(Exception e) {
				System.out.println("3.休眠被中断");
				return;
			}
			System.out.println("4.run()方法正常结束");
		
	}
};
public class ThreadInterruptDemo{
	public static void main(String main[]) {
		MyThread mt1 = new MyThread ();
		Thread t = new Thread (mt1,"线程");
		t.start();
		try{
			Thread.sleep(2000);
			
		}catch(Exception e) {
			
		}
		t.interrupt();
		
	}
}

f.后台线程

  • 只要前台有一个线程在运行,整个Java进程都不会消失,所以此时可以设置一个后台线程,即使java进程结束,后台线程依然会继续执行,通过setDeamon()方法实现;
class MyThread implements Runnable{
	public void run() {
		while(true) {
			System.out.println(Thread.currentThread().getName() +"在运行  ");
		}
		
	}
};
public class ThreadSetDeamon{
	public static void main(String main[]) {
		MyThread mt1 = new MyThread ();
		Thread t = new Thread (mt1,"线程");
		t.start();
		
	}
}

g.线程的优先级

  • 使用 setPriority()方法
  • 三个优先级
  • MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY
class MyThread implements Runnable{
	public void run() {
		for(int i = 0; i < 5;i ++ ){
			try {
				Thread.sleep(500);
			}catch(Exception e) {};
			System.out.println(Thread.currentThread().getName()  + "运行, i=" +i);
		}		
	}
};
public class ThreadPriorityDemo{
	public static void main(String main[]) {
	Thread t1 = new Thread(new MyThread(),"线程a");
	Thread t2 = new Thread(new MyThread(),"线程b");
	Thread t3 = new Thread(new MyThread(),"线程c");
	t1.setPriority(Thread.MIN_PRIORITY);
	t2.setPriority(Thread.NORM_PRIORITY);
	t3.setPriority(Thread.MAX_PRIORITY);
	t1.start();
	t2.start();
	t3.start();		
	}
}

  • 主线程的优先级
public class MainPriorityDemo01{
	public  static void main(String args[]) {
		System.out.println("主函数的优先级" + Thread.currentThread().getPriority());
		System.out.println("MAX_PRIORITY =  " + Thread.MAX_PRIORITY);
		System.out.println("MIN_PRIORITY =  " + Thread.MIN_PRIORITY);
		System.out.println("NORM_PRIORITY =  " + Thread.NORM_PRIORITY);
	}
}

主线程的优先级相当于 NORM_PRIORITY

h.线程的礼让

  • 使用yield()方法
class MyThread implements Runnable{
	public void run() {
		for(int i =0; i < 5 ; i ++) {
			System.out.println(Thread.currentThread().getName()+ "运行 , i = " + i);
			if( i == 3 ) {
				System.out.println("线程礼让");
				Thread.currentThread().yield();
			}
		}
	}
};
public class ThreadYieldDemo01{
	public static void main(String args[]) {
		MyThread mt=new MyThread();
		Thread t1 = new Thread(mt,"线程a");
		Thread t2 = new Thread(mt,"线程b");
		t1.start();
		t2.start();
		
	}
}

6.案例

  • a.继承Thread类
class MyThread extends Thread{
	private int time;
	public MyThread(String name,int time) {
		super(name);
		this.time = time;
	}
	public void run() {
		try {
			Thread.sleep(this.time);
		}catch(Exception e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+ "休眠" + this.time+"毫秒");
		
	}
};
public class ThreadDemo03{
	public static void main(String args[]) {
		MyThread mt1=new MyThread("线程a",1000);
		MyThread mt2=new MyThread("线程b",2000);
		MyThread mt3=new MyThread("线程c",3000);
		mt1.start();
		mt2.start();
		mt3.start();		
	}
}

  • b.使用Runnable接口
class MyThread implements Runnable{
	private int time;
	private String name;
	public MyThread(String name,int time) {
		this.name = name;
		this.time = time;
	}
	public void run() {
		try {
			Thread.sleep(this.time);
		}catch(Exception e) {
			e.printStackTrace();
		}
		System.out.println(this.name+ "休眠" + this.time+"毫秒");
		
	}
};
public class ThreadDemo04{
	public static void main(String args[]) {
		MyThread mt1=new MyThread("线程a",1000);  //此处已命名
		MyThread mt2=new MyThread("线程b",2000);
		MyThread mt3=new MyThread("线程c",3000);
		new Thread(mt1).start();
		new Thread(mt2).start();
		new Thread(mt3).start();
			
	}
}

7. 线程的生命周期

  • suspend():暂时挂起线程
  • resume();恢复挂起的线程
  • stop();停止线程
  • 因为上面的三个方法都会产生死锁,所以现在一般不适用

案例:线程中的停止方法
class MyThread implements Runnable{
private boolean flag = true;

public void run() {
	int i = 0;
	while(this.flag) {
		System.out.println(Thread.currentThread().getName() + "i = " + (i ++));
		
	}
}
public void stop(){
	this.flag = false;
}

}
public class ThreadStopDemo01{
public static void main(String args[]) {
MyThread mt = new MyThread();
Thread t = new Thread(mt,“线程”);
t.start();
try {
Thread.sleep(20);

	}catch(Exception e) {
		e.printStackTrace();
	}
	mt.stop();
}

}

本文地址:https://blog.csdn.net/weixin_45739665/article/details/107351967

《java学习笔记-----多线程.doc》

下载本文的Word格式文档,以方便收藏与打印。