多线程以及其方法概述

一、什么是多线程

Thread类中有这样的明确定义:线程是程序中执行的线程,Java虚拟机允许程序同时运行多个执行线程。

1.线程有5种状态:新建,就绪,运行,阻塞,死亡。(网上有很多说有六种或者七种,其实都表达的一样,等待和睡眠都会导致阻塞)

新建:当使用new操作符创建新线程时,线程处于“新建“状态
就绪:调用start()方法
运行:执行run()方法
阻塞:当线程需要获得对象的内置锁,而该锁正在被其他线程拥有,或者当线程等待其他线程通知调度表可以运行时(即调用sleep()或者wait()方法)
终止:当run()方法运行完毕或调用stop()方法

二、简单的多线程Demo

public class ThreadTest implements Runnable{//或者extends Thread
	@Override
	public void run() {
		// TODO Auto-generated method stub
			for(int i=0;i<3;i++){
				System.out.println("这是线程:"+Thread.currentThread().getName()+" "+i);
			}
	}
	
		public static void main(String[] args) throws InterruptedException {
			//实例化类
			ThreadTest test1=new ThreadTest();
			//创建线程对象,访问同一对象
			Thread t1=new Thread(test1);
			Thread t2=new Thread(test1);	
			//启动线程
			t1.start();
			t2.start();		
		}
}

运行结果:
在这里插入图片描述

三、多线程的sleep方法

多线程的睡眠方法,调用时会一直持有锁资源,其它线程无法访问
1.sleep(long millis) 线程睡眠 millis 毫秒

2.sleep(long millis, int nanos) 线程睡眠 millis 毫秒 + nanos 纳秒
可以看到上面的运行结果是交替运行的
现在将上述main方法中加入sleep方法

public static void main(String[] args) throws InterruptedException {
			//实例化类
			ThreadTest test1=new ThreadTest();
			//创建线程对象
			Thread t1=new Thread(test1);
			Thread t2=new Thread(test1);	
			//启动线程
			t1.start();
			//使线程睡眠2秒
			t1.sleep(2000);
			t2.start();		
		}

运行结果
在这里插入图片描述
t1线程执行完后等待两秒之后才执行t2线程
注意:Sleep是Thread的静态方法,是线程用来控制自身流程的。在main中可以直接调用,这里的t1.sleep等价于Thread.sleep,跟t1无关,它是让使用该方法的线程也就是main方法睡眠两秒。

三、多线程的join方法

join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A,在线程A里面调用了线程B.join方法,则接下来线程B会抢先在线程A面前执行,等到线程B全部执行完后才继续执行线程A。
看例子

public class ThreadTest implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
			for(int i=0;i<3;i++){
				System.out.println("这是线程:"+Thread.currentThread().getName()+" "+i);
			}
	}
	
		public static void main(String[] args) throws InterruptedException {
			//实例化类
			ThreadTest test1=new ThreadTest();
			//创建线程对象
			Thread t1=new Thread(test1);
			Thread t2=new Thread(test1);	
			//启动线程
			t1.start();
			//t1.join表示t1执行完才会执行t2
			t1.join();
			t2.start();		
		}
}

运行结果
在这里插入图片描述
本来的运行结果如第二大章中是混乱的,t1.join表示t1执行完才会执行t2,所以t2会等t1执行完再执行,这样的结果是不是和sleep睡眠之后有点像,但是更多时候还是建议用join特别是在不知道具体睡眠时间的时候。

四、多线程的synchronized关键字

在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在(也就是所谓实例锁。后面可以看到,其实还有可以对整个类上锁的全局锁)。而synchronized就是对象的一个同步锁。这个关键字的作用是,被这个关键字修饰的部分代码,称为互斥区。当某个线程在访问这段代码的时候,其他线程对这段代码的访问是互斥的,被称为临界区。简单的说就是用该关键字修饰的方法类变量被一个线程访问时,其它线程无法访问。
synchronized同步方式主要有3种,简单介绍如下:
1 synchronized同步普通方法,锁是当前对象实例。
2.synchronized同步静态方法,锁是当前类的Class对象。
3.synchronized同步代码块,锁是代码块中的括号里的对象。

  • 1.修饰普通方法和修饰代码块,以下两种是等价
方法一修饰方法

public synchronized void run()
{
   // todo
}
方法二修饰代码块

public void run()
{
   synchronized(this) {
      // todo
   }
}
public class ThreadTest implements Runnable{
	public synchronized void method(){
		for(int i=0;i<3;i++){
			System.out.println("这是线程:"+Thread.currentThread().getName()+" i=="+i);
		}
		/*也可以是synchronized (this) {
			for(int i=0;i<3;i++){
				System.out.println("这是线程:"+Thread.currentThread().getName()+" i=="+i);
			}
		}*/
	}
	@Override
	public  void run() {
		method();
	}
		public static void main(String[] args) throws InterruptedException {
			//实例化两个不同类
			ThreadTest test1=new ThreadTest();
			ThreadTest test2=new ThreadTest();
			//创建线程对象
			Thread t1=new Thread(test1);
			Thread t2=new Thread(test2);	
			//启动线程
			t1.start();
			t2.start();		
		}
}


运行结果:
在这里插入图片描述
代码中,线程调用的是不同的类,此时代码运行结果不再同步,因为锁的是普通方法,也就是对象锁。两个对象不是同一把锁。

  • 2.修饰静态方法
    将method方法改为
public synchronized static void method(){
		for(int i=0;i<3;i++){
			System.out.println("这是线程:"+Thread.currentThread().getName()+" i=="+i);
		}
	}

运行结果:
在这里插入图片描述
这里就算属于不同类也能够同步运行,因为同步静态方法,锁是当前类的Class对象,两个对象是属于同一个类,是同一把锁。

五、多线程的wait方法

wait():等待,如果线程执行了wait方法,那么该线程会进入等待的状态,等待状态下的线程必须要被其他线程调用notify()方法才能唤醒。等待时会释放锁资源。
notify():唤醒,随机唤醒线程池等待线程其中的一个。
notifyAll():唤醒线程池所有等待线程。

注意:
wait与notify方法要注意的事项:

  1. wait方法与notify方法是属于Object对象的。
  2. wait方法与notify方法必须要在同步代码块或者是同步函数中才能使用。
  3. wait方法与notify方法必须要由所对象调用。

当在一个对象实例上调用wait()方法后,当前线程就会在这个对象上等待。直到另外的线程调用了notify()方法,出于等待的线程才得以继续进行。这样,多线程之间的协作就可以用这两个方法进行通信了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值