JAVA多线程及线程锁

Java多线程

1、背景
每个Java程序都有一个默认的主线程main。如果main方法中又创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法即使执行完最后的语句(主线程结束),JVM也不会结束Java应用程序,JVM一直要等到Java应用程序中的所有线程都结束之后,才会结束Java程序。

2、线程的状态和生命周期
Java中使用Thread类及其子类对象来表示线程。

(1).新建
(2).运行
(3).中断:

JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU使用权进入休眠状态
线程使用期间执行了sleep(int millsecond)方法,是当前线程进入休眠状态,等待millsecond毫秒后重新进入排队队列等待CPU资源,以便在中断处继续运行
线程使用CPU期间,执行了wait()方法,是当前线程进入等待状态,不会主动进入到线程队列中排队等待CPU资源,必须有其他线程调用notify()方法通知他使他从新回到线程队列中等待CPU资源,以便在中断处继续运行
线程使用CPU资源期间,执行了某个操作进入阻塞状态,比如执行读/写操作引起的阻塞。进入阻塞状态的线程不能进入排队队列,只有当引起阻塞的原因消除时,线程才重新进到线程队列中排队等待CPU资源,以便从原来中断处开始继续运行

(4).死亡
正常运行完run()方法
被提前强制终止run()方法

注:
在java中,多个线程同时执行可能会造成线程安全问题(线程之间同时拥有一个变量,且发生了修改),为了避免这个问题,需要线程锁(synchronized)来使一个线程执行时,其他线程会等待这个线程执行完毕才执行,而不是”同时“执行。

3、 Thread常用方法
*1.start():启动当前的线程,调用当前线程的run()
*2.run():通常需要重写Thread类中的此方法,将创建要执行的操作声明在此方法中
*3.currentThread():静态方法,返回代码执行的线程
*4.getName():获取当前线程的名字
*5.setName():设置当前线程的名字
*6.yield():释放当前CPU的执行
*7.join():在线程a中调用线程b的join()方法,此时线程a进入阻塞状态
*8.stop():已过时的方法,当执行此方法是,强制结束当前进程
*9.sleep(long millitime):让当前进程睡眠指定的毫秒数,在指定时间内,线程是阻塞状态
*10.isAlive():判断进程是否存活

4、举个栗子

package day06;
/**
 * 多线程安全并发问题
 * 当多线程并发操作到了同一临界资源时,由于线程切换的时间不确定,
 * 导致操作未按程序设计的执行,运行出现混乱,严重时可能导致系统瘫痪
 * 
 * 临界资源:只能被单线程操作的资源
 * @author ASUS
 *
 */
public class synTest1 {
	public static void main(String[] args) {
		Table t = new Table();
		Thread t1 = new Thread(){		//创建一个线程
			public void run(){		//重写run( )方法,将需要执行的操作声明在此方法中
				while(true){
					//bean变量用来记录拿了多少颗豆子
					int bean = t.getBean();
					if(t.getBean()<0){
						break;
					}
					Thread.yield();		// 暂停当前正在执行的线程对象,并执行其他线程。 
					System.out.println(getName()+":"+bean);
				}
			}
		};
		Thread t2 = new Thread(){
			public void run(){
				while(true){
					//bean变量用来记录拿了多少颗豆子
					int bean = t.getBean();
					if(t.getBean()<0){
						break;
					}
					Thread.yield();
					System.out.println(getName()+":"+bean);
				}
			}
		};
		t1.start();
		t2.start();
	}
	/*
	 * 给线程定义一个小游戏
	 * 
	 * 这里需要两个线程来完成,从桌子上拿豆子
	 * 
	 * 当一个方法使用了synchronized修饰后,该方法就称为同步方法。也就是说超过一个线程就不可以在方法内部执行
	 * 将多个线程并发操作临界资源改为同步执行时,就可以解决多线程并发的安全问题
	 */
	
}
class Table{
	private int beans = 20;
	
	public synchronized int getBean(){
		//让线程主动放弃CPU时间,模拟线程执行到这里就没有时间了
		Thread.yield();
		return beans--;
	}
}

概念补充:

一、线程概念
线程可以理解为在进程中独立运行的子任务。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

二、线程与进程的区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。

三、与线程相关的三个概念
串行:一个线程执行到底,相当于单线程。

并发:多个线程交替执行,抢占cpu的时间片,但是速度很快,在宏观角度看来就像是多个线程同时执行。

并行:多个线程在不同的cpu中同时执行。

四、在Java的开发包中,已经自带对多线程技术支持。实现对多线程编程的方式有两种,一种是继承Thread类,第二种是实现Runnable接口,第三种是实现Callable接口。常用的为前两者。先来看看Thread类结构

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值