java线程概述

进程:一个独立的控制单元,在这里面完成系统资源的分配及调用。
线程:存在进程中,一个进程最少得有一个线程(执行路径)。main方法其实就是一个主线程。

线程是一个事物,事物需要用类来描述,那么这个事物又特别常见,
Java工程考虑到这个问题,他就帮我们描述好了这个事物。


创建线程的方式有两种
1.继承Thread类,重写run方法
2.实现Runnable接口,重写run方法(最好使用这种方式创建线程)
  好处:可扩展性更强,可以在实现线程的同时还能与其他类建立子父类关系。

start和run方法的区别:
1.run就是一个普通的方法,被当前线程执行。

2.start 被执行后会创建一个新的线程,然后这个新线程去执行run方法中的代码


获取当前线程对象可以通过currentThread()方法来完成,


线程不安全的原因:
当多条语句操作线程共享数据,然后某个线程只执行了多条语句的一部分
(CPU执行权就被其他线程拿去了),导致线程共享数据错误。

那么如何解决线程安全问题?
只需要保证多条语句同时只能被一个线程执行,当这个线程执行完成后,
其他线程才能开始执行,就保证共享数据不会出现错误,java就提供有效的解决方案(线程同步)
同步代码块格式:
synchronized(对象)
{
需要同步的代码;
}
同步的作用:保证同步代码块中的代码同一时刻只能被一个线程执行。但是有两个前提:
1.同步需要两个或者两个以上的线程。
2.多个线程使用的是同一个锁。

例:简单的售票程序

class ShouPiao extends Thread
{
	private static Object obj=new Object();
	private static int count=100;
	public void run(){
		while(true){
			synchronized(obj)
			{
				count--;
				if(count<=0)
					break;
				try{Thread.sleep(10);}catch(Exception e){};
				System.out.println(getName()+":"+count);
			}
		}
	}
}
class Test{
	public static void main(String[] args){
		ShouPiao th1=new ShouPiao();
		th1.start();
		ShouPiao th2=new ShouPiao();
		th2.start();
		ShouPiao th3=new ShouPiao();
		th3.start();
		ShouPiao th4=new ShouPiao();
		th4.start();
	}
}

同步函数
与同步代码块原理一样,只是表现方式不同,可以保证同一时刻只能有一个线程执行此方法。

同步函数的锁就是this,静态同步函数的锁是本类字节码对象。


死锁

class My implements Runnable
{
	private static boolean flag;
	public void run(){
		for(int i=0;i<3;i++){
			if(flag){
				synchronized(MyLock.obj2){
					flag=false;
					System.out.println("A-锁2");
					try{Thread.sleep(1000);}catch(Exception e){};
					synchronized(MyLock.obj1){
						System.out.println("A-锁1");
					}
				}
			}else{
				synchronized(MyLock.obj1){
					flag=true;
					System.out.println("B-锁1");
					try{Thread.sleep(1000);}catch(Exception e){};
					synchronized(MyLock.obj2){
						System.out.println("B-锁2");
					}
				}
			}
		}
	}
}
class MyLock{
	public static Object obj1=new Object();
	public static Object obj2=new Object();
}
class Test
{
	public static void main(String[] args){
		My my=new My();
		Thread th1=new Thread(my);
		th1.start();
		Thread th2=new Thread(my);
		th2.start();
	}
}

等待wait()与唤醒notify()

wait()使当前持有锁的线程进入等待状态(注:进入等待状态的线程被唤醒后继续执行后面的程序,不需要执行之前的程序),notify()唤醒通过锁对象进入等待状态的线程(如有多个等待线程,通常先唤醒最先进入等待状态的线程)。

notify()只能唤醒单个程序,唤醒的是自己方的进程则可能导致线程全部进入等待状态,notifyAll()唤醒线程池中所有等待的线程。


停止线程:

改变线程循环标记。

class MyThread extends Thread
{
	private boolean flag=true;
	public void run(){
		while(flag){
			System.out.println("run...");		
		}
	}
	public void setFlag(boolean flag){
		this.flag=flag;
	}

}
class Test
{
	public static void main(String[] args){
		MyThread th=new MyThread();
		th.start();
		try{Thread.sleep(1000);}catch(Exception e){};
		for(int i=0;i<100;i++){
			if(i==99){
				th.setFlag(false);
			}
		}
	}
}

interrupt中断线程的阻塞状态

在下面代码中,th.interrupt()中断了Thread.sleep(50000)。

将上一段代码run方法改为

public void run(){
		while(flag){
			try{Thread.sleep(50000);}catch(Exception e){
				System.out.println(e.getMessage());
			};
			System.out.println("run...");		
		}
	}
main方法改为

public static void main(String[] args){
		MyThread th=new MyThread();
		th.start();
		try{Thread.sleep(1000);}catch(Exception e){};
		for(int i=0;i<100;i++){
			if(i==99){
				th.interrupt();//中断阻塞状态
				th.setFlag(false);
			}
		}
	}

守护线程:当进程中只存在守护线程后,进程结束。
例:在这段代码for循环执行100次时主线程结束,进程中只存在守护线程,则进程结束。

class MyThread extends Thread
{
	public void run(){
		while(true){
			System.out.println("...."+getName());
		}
	}
}
class Test
{
	public static void main(String[] args){
		MyThread th1=new MyThread();
		MyThread th2=new MyThread();
		th1.setDaemon(true);//更改为守护线程
		th2.setDaemon(true);//更改为守护线程
		th1.start();
		th2.start();
		for(int i=0;i<100;i++){
			System.out.println(i);
		}
	}
}

join方法
1.这个方法在哪个线程中被调用,就会让哪个线程失去CPU执行权
2.哪个线程对象调用join,那么只有等这个对象的线程结束,执行该调用的线程才有可执行权。

在下面代码中主线程调用join方法,则主线程失去CPU执行权,th1和th2争夺CPU执行权。因为th1调用join方法,因此在th1执行完后主线程才有执行权(若此时th2还未执行完,则主线程和th2争夺CPU执行权)。

class MyThread extends Thread
{
	public void run(){
		for(int i=0;i<10;i++){
			try{Thread.sleep(100);}catch(Exception e){};
			System.out.println(getName()+"...."+i);
		}
	}
}
class Test
{
	public static void main(String[] args){
		MyThread th1=new MyThread();
		MyThread th2=new MyThread();
		th1.start();
		th2.start();
		try{th1.join();}catch(InterruptedException e){
			System.out.println(e.getMessage());
		};
		for(int i=0;i<100;i++){
			System.out.println(i);
		}
	}
}









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值