Java——线程

创建线程

定义+创建+启动

  1. 创建线程的第一种方式:继承Thread类
public class Test{
	public static void main(String[] args){
		Thread thread=new Process();
		thread.start();
		for(int i=0;i<3;i++)
			System.out.println("ooo");
	}
}

class Process extends Thread{
	public void run()
	{
		for(int i=0;i<5;i++)
			System.out.println("haha");
	}
}

在这里插入图片描述
2. 创建线程的第二种方式:实现Runnable接口

public class Test{
	public static void main(String[] args){
		Thread thread=new Thread(new Process());
		thread.start();
		for(int i=0;i<3;i++)
			System.out.println("ooo");
	}
}

class Process implements Runnable{
	public void run(){
		for(int i=0;i<5;i++)
			System.out.println("haha");
	}
}

在这里插入图片描述

线程命名

public class Test{
	public static void main(String[] args){
		Thread thread=new Thread(new Process());
		thread.start();
		//获取主线程对象
		Thread mThread=Thread.currentThread();
		//获取主线程名称
		System.out.println(mThread.getName());
		//给线程命名
		mThread.setName("main");
		
		System.out.println(Thread.currentThread().getName());
	}
}

class Process implements Runnable{
	public void run(){
		Thread t=Thread.currentThread();
		System.out.println(t.getName());
		t.setName("t1");
		System.out.println(Thread.currentThread().getName());
	}
}

在这里插入图片描述

线程优先级

//优先级高的线程获得的时间片相对多一些
//优先级:1-10  最高:10  最低:1  默认:5
public class Test{
	public static void main(String[] args){
		Thread t1=new Thread(new Process());
		Thread t2=new Thread(new Process());
		
		//获取线程优先级
		System.out.println(t1.getPriority());
		System.out.println(t2.getPriority());
		
		t1.setName("t1");
		t2.setName("t2");
		
		//设置线程优先级
		t1.setPriority(1);
		t2.setPriority(10);
		
		//启动线程
		t1.start();
		t2.start();
	}
}

class Process implements Runnable{
	public void run(){
		for(int i=0;i<10;i++)
			System.out.println(Thread.currentThread().getName()+"--->"+i);
	}
}

在这里插入图片描述

线程休眠

腾出CPU给其他的线程
1、

public class Test{
	public static void main(String[] args){
		Thread t1=new Thread(new Process());
		t1.start();
	}
}

class Process implements Runnable{
	public void run(){
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
			try{
				Thread.sleep(1000);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}
public class Test{
	public static void main(String[] args) throws InterruptedException {
		Thread t1=new Thread(new Process());
		t1.setName("t1");
		t1.start();
		
		for(int i=0;i<20;i++)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
			Thread.sleep(500);//阻塞的是当前线程
		}
	}
}//main方法可以抛出异常

class Process implements Runnable{
	public void run(){
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
			try{
				Thread.sleep(1000);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}//run方法为重写Thread类中的run方法,Thread类中的run方法不抛出异常,因此重写的方法不能抛出更多的异常
}

在这里插入图片描述

public class Test{
	public static void main(String[] args) throws InterruptedException {
		Thread t1=new Thread(new Process());
		t1.setName("t1");
		t1.start();
		
		t1.sleep(5000);//相当于Thread.sleep(5000);
		System.out.println("Hello world!");
	}
}

class Process implements Runnable{
	public void run(){
		for(int i=0;i<10;i++)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
		}
		System.out.println("线程结束");
	}
}

在这里插入图片描述

2、

//线程正在休眠,打断其休眠
public class Test{
	public static void main(String[] args) throws InterruptedException {
		Thread t1=new Thread(new Process());
		t1.setName("t1");
		t1.start();
		
		Thread.sleep(5000);
		t1.interrupt();//是通过抛出InterruptedException异常来实现的,try...catch语句结束
	}
}//main方法可以抛出异常

class Process implements Runnable{
	public void run(){
		try{
			Thread.sleep(10000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		for(int i=0;i<5;i++)
			System.out.println(Thread.currentThread().getName()+"--->"+i);
	}//run方法为重写Thread类中的run方法,Thread类中的run方法不抛出异常,因此重写的方法不能抛出更多的异常
}

在这里插入图片描述
3、

//如何正确的更好的终止一个正在执行的线程
public class Test{
	public static void main(String[] args) throws InterruptedException {
		Process process =new Process();
		Thread t1=new Thread(process);
		t1.setName("t1");
		t1.start();
		
		Thread.sleep(5000);
		process.run=false;
	}
}

class Process implements Runnable{
	boolean run=true;
	public void run(){
		for(int i=0;i<1000;i++)
		{
			if(run)
			{
				System.out.println(Thread.currentThread().getName()+"--->"+i);
			}
		}
		System.out.println("线程结束");
	}
}

在这里插入图片描述

线程合并

合并后变为单线程,只能一个线程执行完后,另一个线程才能执行

public class Test{
	public static void main(String[] args) throws InterruptedException {
		Thread t1=new Thread(new Process());
		t1.setName("t1");
		t1.start();
		t1.join();
		for(int i=0;i<20;i++)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
		}
	}
}

class Process implements Runnable{
	public void run(){
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
		}
	}
}

在这里插入图片描述

线程同步:为了保证共享数据的安全

//演示不使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作
public class Test{
	public static void main(String[] args) {
		Account account =new Account("Jack", 5000.0);
		Process process =new Process(account);
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.start();
		t2.start();
	}
}

class Account{
	private String name;
	private double yukuan;
	
	Account(String name,double yukuan){
		this.name=name;
		this.yukuan=yukuan;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getYukuan() {
		return yukuan;
	}

	public void setYukuan(double yukuan) {
		this.yukuan = yukuan;
	}
	//对外提供取款操作
	public void delete(double money) throws InterruptedException
	{
		double after=this.yukuan-money;
		Thread.sleep(1000);
		this.yukuan=after;
		System.out.println("取款成功,剩余额为"+this.yukuan);
	}
}

class Process implements Runnable{
	 Account account ;
	 
	 Process(Account account)
	 {
		 this.account=account;
	 }
	 public void run(){
		 try{account.delete(1000.0);}
		 catch(InterruptedException e){
			 e.printStackTrace();
		 }
	 }
 }

在这里插入图片描述

double after=this.yukuan-money;
		Thread.sleep(1000);
		this.yukuan=after;
		System.out.println("取款成功,剩余额为"+this.yukuan);

同一时间只能有一个线程执行上述代码。将需要同步的代码放到synchronized(共享对象){…}中,构成同步语句块

//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
	public static void main(String[] args) {
		Account account =new Account("Jack", 5000.0);
		Process process =new Process(account);
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.start();
		t2.start();
	}
}

class Account{
	private String name;
	private double yukuan;
	
	Account(String name,double yukuan){
		this.name=name;
		this.yukuan=yukuan;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getYukuan() {
		return yukuan;
	}

	public void setYukuan(double yukuan) {
		this.yukuan = yukuan;
	}
	//对外提供取款操作
	public void delete(double money) throws InterruptedException
	{
		//变为单线程
		synchronized (this) {
			double after=this.yukuan-money;
			Thread.sleep(1000);
			this.yukuan=after;
			System.out.println("取款成功,剩余额为"+this.yukuan);
		}
		
	}
}

class Process implements Runnable{
	 Account account ;
	 
	 Process(Account account)
	 {
		 this.account=account;
	 }
	 public void run(){
		 try{account.delete(1000.0);}
		 catch(InterruptedException e){
			 e.printStackTrace();
		 }
	 }
 }

在这里插入图片描述
发现代码的执行时间增长,代码的执行效率降低,但是数据的安全性得到了保证
原理: t1线程执行到同步语句块,遇到了synchronized关键字,就会去找synchronized(共享对象)内共享对象的对象锁,如果找到,则进入同步语句块执行程序,当同步语句块中的代码执行结束之后,t1线程归还共享对象的对象锁;在t1线程执行同步语句块的过程中,如果t2线程也过来执行同步语句块,就也要去找共享对象的对象锁,但是该对象锁被t1线程持有,所以t2线程只能等待t1线程执行完归还对象锁后才去执行同步语句块

在java中任何一个对象都有对象锁,即每一个对象都有0、1标志
第二种线程同步的方式

//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
	public static void main(String[] args) {
		Account account =new Account("Jack", 5000.0);
		Process process =new Process(account);
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.start();
		t2.start();
	}
}

class Account{
	private String name;
	private double yukuan;
	
	Account(String name,double yukuan){
		this.name=name;
		this.yukuan=yukuan;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getYukuan() {
		return yukuan;
	}

	public void setYukuan(double yukuan) {
		this.yukuan = yukuan;
	}
	//对外提供取款操作
	public synchronized void delete(double money) throws InterruptedException
	{
		double after=this.yukuan-money;
		Thread.sleep(1000);
		this.yukuan=after;
		System.out.println("取款成功,剩余额为"+this.yukuan);	
	}
}

class Process implements Runnable{
	 Account account ;
	 
	 Process(Account account)
	 {
		 this.account=account;
	 }
	 public void run(){
		 try{account.delete(1000.0);}
		 catch(InterruptedException e){
			 e.printStackTrace();
		 }
	 }
 }

在这里插入图片描述
synchronized关键字加到成员方法上
其实还是去找当前对象this的对象锁
一般采用第一种方式,第二种方式用于成员方法中所有的代码都需要同步的情况,此时程序的执行效率可能十分低下

StringBuffer、Vector、HashTabel类内含synchronized,因此它们都是线程安全的

遇synchronized就去找锁,找得到就去执行,找不到就等

//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
	public static void main(String[] args) throws InterruptedException{
		Account account =new Account();
		Process process =new Process(account);
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		//若想让m1方法先执行,可以添加延迟
		Thread.sleep(1000);
		t2.start();
	}
}

class Account{
	public synchronized void m1() throws InterruptedException
	{
		Thread.sleep(2000);
		System.out.println("m1 is doing...");
	}
	//m2没有synchronized,不会去找对象锁,不是线程同步,不会等m1
	public void m2(){
		System.out.println("m2 is doing...");
	}
}

class Process implements Runnable{
	 Account account ;
	 
	 Process(Account account)
	 {
		 this.account=account;
	 }
	 public void run(){
		 if(Thread.currentThread().getName()=="t1")
		 {
			 try{
				 account.m1();
			 }catch(InterruptedException e)
			 {
				 e.printStackTrace();
			 }
		 }
		 else if(Thread.currentThread().getName()=="t2")
			 account.m2();
	 }
 }

在这里插入图片描述

//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
	public static void main(String[] args) throws InterruptedException{
		Account account =new Account();
		Process process =new Process(account);
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		//若想让m1方法先执行,可以添加延迟
		Thread.sleep(1000);
		t2.start();
	}
}

class Account{
	public synchronized void m1() throws InterruptedException
	{
		Thread.sleep(2000);
		System.out.println("m1 is doing...");
	}
	//m2有synchronized,就会去找对象锁,而对象又是共享的,是线程同步,m2会等m1
	public synchronized void m2(){
		System.out.println("m2 is doing...");
	}
}

class Process implements Runnable{
	 Account account ;
	 
	 Process(Account account)
	 {
		 this.account=account;
	 }
	 public void run(){
		 if(Thread.currentThread().getName()=="t1")
		 {
			 try{
				 account.m1();
			 }catch(InterruptedException e)
			 {
				 e.printStackTrace();
			 }
		 }
		 else if(Thread.currentThread().getName()=="t2")
			 account.m2();
	 }
 }

在这里插入图片描述

//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
	public static void main(String[] args) throws InterruptedException{
		Account account1 =new Account();
		Account account2 =new Account();
		Process process1 =new Process(account1);
		Process process2 =new Process(account2);
		Thread t1=new Thread(process1);
		Thread t2=new Thread(process2);
		//都没有共享对象,不是线程同步,m2不会等m1
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		//若想让m1方法先执行,可以添加延迟
		Thread.sleep(1000);
		t2.start();
	}
}

class Account{
	public synchronized void m1() throws InterruptedException
	{
		Thread.sleep(2000);
		System.out.println("m1 is doing...");
	}
	public synchronized void m2(){
		System.out.println("m2 is doing...");
	}
}

class Process implements Runnable{
	 Account account ;
	 
	 Process(Account account)
	 {
		 this.account=account;
	 }
	 public void run(){
		 if(Thread.currentThread().getName()=="t1")
		 {
			 try{
				 account.m1();
			 }catch(InterruptedException e)
			 {
				 e.printStackTrace();
			 }
		 }
		 else if(Thread.currentThread().getName()=="t2")
			 account.m2();
	 }
 }

在这里插入图片描述

类锁:锁是类级别的,只有一个

在静态方法上添加synchronized关键字

public class Test{
	public static void main(String[] args) throws InterruptedException{
		Process process =new Process();
		
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.setName("t1");
		t2.setName("t2");
		
		t1.start();
		Thread.sleep(1000);
		t2.start();
	}
}

class Process implements Runnable{
	public void run()
	{
		if(Thread.currentThread().getName()=="t1")
		{
			try{
				Myclass.m1();
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}
			
		else if(Thread.currentThread().getName()=="t2")
			Myclass.m2();
	}
}

class Myclass{
	public synchronized static void m1() throws Exception
	{
		Thread.sleep(2000);
		System.out.println("m1 is doing...");
	}
	
	public static void m2(){
		System.out.println("m2 is doing...");
	}//m2没有synchronized修饰,不会去找类锁,所以m2不会去等m1
}

在这里插入图片描述

public class Test{
	public static void main(String[] args) throws InterruptedException{
		Process process =new Process();
		
		Thread t1=new Thread(process);
		Thread t2=new Thread(process);
		t1.setName("t1");
		t2.setName("t2");
		
		t1.start();
		Thread.sleep(1000);
		t2.start();
	}
}

class Process implements Runnable{
	public void run()
	{
		if(Thread.currentThread().getName()=="t1")
		{
			try{
				Myclass.m1();
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}
			
		else if(Thread.currentThread().getName()=="t2")
			Myclass.m2();
	}
}

class Myclass{
	public synchronized static void m1() throws Exception
	{
		Thread.sleep(2000);
		System.out.println("m1 is doing...");
	}
	
	public synchronized static void m2(){
		System.out.println("m2 is doing...");
	}//m2有synchronized修饰,会去找类锁,所以m2会等m1
}

在这里插入图片描述

public class Test{
	public static void main(String[] args) throws InterruptedException{
		//不同对象
		Myclass myclass =new Myclass();
		Myclass myclass2 =new Myclass();
		Process process =new Process(myclass);
		Process process2 =new Process(myclass2);
		
		Thread t1=new Thread(process);
		Thread t2=new Thread(process2);
		//类锁,与对象无关,所以m2会去等m1
		t1.setName("t1");
		t2.setName("t2");
		
		t1.start();
		Thread.sleep(1000);
		t2.start();
	}
}

class Process implements Runnable{
	Myclass myclass;
	
	Process(Myclass myclass)
	{
		this.myclass=myclass;
	}
	public void run()
	{
		if(Thread.currentThread().getName()=="t1")
		{
			try{
				Myclass.m1();
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}
			
		else if(Thread.currentThread().getName()=="t2")
			Myclass.m2();
	}
}

class Myclass{
	public synchronized static void m1() throws Exception
	{
		Thread.sleep(2000);
		System.out.println("m1 is doing...");
	}
	
	public synchronized static void m2(){
		System.out.println("m2 is doing...");
	}
}

在这里插入图片描述

死锁:前提还是共享,有两个共享对象

t1线程已经锁了o1,还要去锁o2;而t2线程已经锁了o2,还要去锁o1
t1、t2线程都不能执行完去释放各自拥有的锁,陷入僵持局面

public class Test{
	public static void main(String[] args) throws InterruptedException{
		Object o1=new Object();
		Object o2=new Object();
		//两个线程共享对象,如果都不是同一个对象的话怎么会造成死锁呢
		Thread t1=new Thread(new Process(o1,o2));
		Thread t2=new Thread(new Process2(o1,o2));
		t1.start();
		t2.start();
		
	}
}
//两个线程所执行的run方法操作不同,所以可以写两个线程类
class Process implements Runnable{
	Object o1;
	Object o2;
	Process(Object o1,Object o2)
	{
		this.o1=o1;
		this.o2=o2;
	}
	public void run()
	{
		synchronized(o1){
			System.out.println("我已将o1上锁,我还想去锁o2");
			try{
				Thread.sleep(2000);
			}catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			synchronized(o2){
				
			}
		}
	}
}

class Process2 implements Runnable{
	Object o1;
	Object o2;
	Process2(Object o1,Object o2)
	{
		this.o1=o1;
		this.o2=o2;
	}
	public void run(){
		synchronized(o2){
			System.out.println("我已将o2上锁,我还想去锁o1");
			try{
				Thread.sleep(2000);
			}catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			synchronized(o1){
				
			}
		}
	}
}

在这里插入图片描述
总结: 线程同步靠的就是锁,而线程同步的前提是 共享 类或对象,这点很重要

守护线程

线程可分为用户线程和守护线程,守护线程在所有用户线程都结束后才能结束,如java的垃圾回收器就是一个守护线程,在应用程序的所有线程都结束后才能结束
JVM会自动启动一个主线程和垃圾回收器(守护线程)

守护线程一般都是无限执行的,在所有用户线程结束后自动结束

public class Test{
	public static void main(String[] args) throws InterruptedException{
		Thread t1=new Thread(new Process());
		t1.setName("t1");
		t1.start();
		
		for(int i=0;i<10;i++)
			System.out.println(Thread.currentThread().getName()+"--->"+i);
		
		//此时t1为用户线程,会一直进行,主线程结束后t1也会继续执行
	}
}

class Process implements Runnable{
	public void run(){
		int i=0;
		while(true)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
			i++;
			try{
				Thread.sleep(1000);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}
public class Test{
	public static void main(String[] args) throws InterruptedException{
		Thread t1=new Thread(new Process());
		t1.setName("t1");
		t1.setDaemon(true);//设置为守护线程
		t1.start();
		
		for(int i=0;i<10;i++)
			System.out.println(Thread.currentThread().getName()+"--->"+i);
		
		//此时t1为守护线程,主线程结束后没有其他的用户线程了,t1会自动结束
	}
}

class Process implements Runnable{
	public void run(){
		int i=0;
		while(true)
		{
			System.out.println(Thread.currentThread().getName()+"--->"+i);
			i++;
			try{
				Thread.sleep(1000);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}

在这里插入图片描述

定时器Timer:每隔一段固定的时间执行一段固定的代码

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Test{
		public static void main(String[] args) throws Exception{
			//创建定时器
			Timer timer=new Timer();
			//指定定时任务
			timer.schedule(new LogTimerTask(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").parse("2020-09-06 16:50:00 000"),10*1000);
		}
	}

class LogTimerTask extends TimerTask{
	public void run(){
		System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
	}
}
	
/*
 * void schedule(TimerTask task,Date firstTime,long period):安排指定的任务在指定的时间开始进行重复的固定延迟执行,会抛出异常
 * 
 * public abstract class TimerTask extends Object implements Runnable:TimerTask是一个抽象类,类内有run抽象方法
 * abstract void run():此计时器任务要执行的操作
 * 
 */

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值