Java多线程

什么是线程?

进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击左面的IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。目前操作系统都支持多进程。

注意:用户每启动一个进程,操作系统就会为该进程分配一个独立的内存空间。请注意是独立的内存空间

线程的五种状态:

  1. 新建状态(new)

  2. 就绪状态(Runnable)

  3. 运行状态(Running)

  4. 阻塞状态(Blocked)

  5. 死亡状态(Dead)

在这里插入图片描述

创建线程的两种方式:

1、继承Thread类

Java提供了java.lang.Thread类支持多线程编程

public class MyThread extends Thread{
	public void run(){
		for (int i = 1; i < 10; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start(); //调用start()方法启动线程
		thread.run();				
	}
}

在这里插入图片描述
注意:如果直接调用run()方法的话,则是使用主线程运行。
如果调用start()方法的话,则是一条单独的子线程。

2、实现Runnable接口:

  1. 实现run()方法;

  2. 编写线程执行体;

  3. 创建线程对象;

  4. 调用start()方法启动线程。

public class MyRunnable implements Runnable {

	//Runnable中包含run()方法,必须重写run()
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 1; i < 10; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyRunnable runnable = new MyRunnable();
		MyRunnable runnable1 = new MyRunnable();
		
		Thread thread = new Thread(runnable);
		Thread thread1 = new Thread(runnable1);
		
		thread.start();
		thread1.start();
		
	}
}

这里使用两个对象调用start()方法,则是两条线程交替执行。

结果如下图:

在这里插入图片描述

Thread类和Runnable接口的区别:

一、继承Thread类
  编写简单,可直接操作线程
  适用于单继承
二、实现Runnable接口
  避免单继承局限性
  便于共享资源

主线程

main()方法即为主线程入口
产生其他子线程的线程
必须最后完成执行,因为它执行各种关闭动作

线程的休眠

在程序中允许一个线程进行暂时休眠,直接使用Thread.sleep()方法即可实现线程的休眠。

sleep()方法会让当前线程休眠(停止执行)millis毫秒,线程由运行中的状态进入不可运行状态,睡眠时间过后会再次进入可运行状态。

注意:调用sleep()方法需处理InterruptedException异常

public class Sleep implements Runnable {

	public void run() {
		for (int i = 0; i < 5; i++) {
			try {
				Thread.sleep(1000);  //睡眠一秒
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(i+1+"秒");
		}	
	}	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread td = new Thread(new Sleep());
		td.start();
	}
}

结果如下图所示:
在这里插入图片描述

线程的强制执行

join()方法使当前线程暂停执行,等待调用该方法的线程结束后再继续执行本线程。

注意:调用join()方法需处理InterruptedException异常

public class JoinDemo implements Runnable{

	public void run() {
		for (int i = 0; i <10; i++) {
			try {
				Thread.sleep(10); //增加线程交替执行的几率
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}  
			//输出当前线程的信息
			System.out.println(Thread.currentThread().getName()+"运行:"+i);
		}		
	}
	
	public static void main(String[] args) {
		//创建子线程并启动
		Thread td = new Thread(new JoinDemo());
		td.start();
		for (int i = 0; i < 20; i++) {
			if (i == 5) {
				try {
					td.join(); //阻塞主线程,子线程强制执行
				} catch (InterruptedException e) {
					e.printStackTrace();
				}			
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"运行:"+i);
		}
	}
}

结果如下图所示:
在这里插入图片描述

线程的同步

当两个或多个线程需要访问同一资源时,需要以某种顺序来确保该资源某一时刻只能被一个线程使用,这就称为线程同步。

采用线程同步来控制线程的执行有两种方式,即同步代码方法和同步代码块。这两种方式均使用synchronized关键字来实现。

1、同步方法

public class Site implements Runnable{
	private int count = 10;  //剩余票数
	private int num = 0;   //买到第几张票
	private boolean flag = false;  //记录是否售完
	
	public void run() {
		// TODO Auto-generated method stub
		while(!flag){
		sale();
    }
  }
  //同步方法:售票
  public synchronized void sale(){
	  if (count <= 0) {
		flag = true;
		return;
	}
	  //第一步:修改数据
	  num++;
	  count--;
	  try {
		Thread.sleep(500); //模拟网络延迟
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} 
	  //第二步:显示信息
	  System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票");
  }
}

2、同步代码块

public class Site implements Runnable{
	private int count = 10;  //剩余票数
	private int num = 0;   //买到第几张票
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			synchronized (this) {  //同步代码块
				//没有余票时,跳出循环
				if (count <= 0) {
					break;
				}
				//第一步:修改数据
				num++;
				count--;
				try{
					Thread.sleep(500);  //模拟网络延时
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票");
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值