Java多线程简析

进程:正在运行的程序,由操作系统分配独立的内存空间和系统资源。

 

线程:线程是进程的一部分,必须依赖进程。线程共享进程的内存空间和系统资源。

 

关系:一个进程拥有多个线程,一个线程只属于一个进程。

 


一、线程生命周期:

 

1、新建状态:当线程创建之后就进入了新建状态。保持这个状态直到启动线程。


2、就绪状态: 当线程调用了start()方法后便进入了就绪状态。等待cpu的调度。就绪状态时线程的入口,要想进入运行状态,就必须先处于就绪状态。


3、运行状态:当cpu开始调度已经处于就绪的线程,线程才进入运行状态,才开始正式运行。


4、阻塞状态:当线程运行中遇到了yield(),wait(),sleep()就会使线程进入阻塞状态,直到再次进入就绪状态,才有机会被cpu调度重新进入运行状态。


5、死亡状态:线程运行结束或者遇到异常,就会进入死亡状态,结束该线程的生命周期。


二、线程的创建:

线程创建有三种基本方式:

 

1、继承Thread类,重写run()方法:

public class TestThread {
	
	public static void main(String[] args) {
		MyThread m=new MyThread();
		m.start();//启动线程
	}
}


/***
 * 通过继承创建线程 重写run()方法
 * @author otote
 *
 */
public class MyThread extends Thread{
	
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println(i);
		}
	}
}

2、实现Runnable接口,重写run()方法。

public class TestRunnable {
	public static void main(String[] args) {
		MyRunnable m=new MyRunnable();
		new Thread(m).start();//启动线程
	}
}


public class MyRunnable implements Runnable{
	
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println(Thread.currentThread().getName()+i);
		}
	}
}


3、使用Callable和Future接口创建线程。

public class TeestCallable {
	public static void main(String[] args) throws Exception{
		Callable<Integer> callable=new MyCallable();
		FutureTask<Integer> futureTask=new FutureTask<>(callable);//用FutureTask来包装MyCallable对象
		
                new Thread(futureTask).start();
		int sum=futureTask.get();//获取值
		System.out.println(sum);
	}
}



public class MyCallable implements Callable<Integer>{

	@Override
	public Integer call() throws Exception {
		int sum=0;
		for(int i=0;i<100;i++) {
			sum+=i;
		}
		return sum;
	}

}

继承Thead的线程类不能再继承其他的类,扩展性差;实现Runnable的任务类还可以再继承其他的类和实现另外的接口,扩展性好。
当两个线程的资源共享时,实现Runnable接口的方式实现线程更好。


三、线程的优先级:

调用setPriority()可为线程设置优先级。

优先级越高的线程,抢占资源的概率大。并不是绝对的。


四、线程的阻塞

引起线程阻塞的方法:

1、线程睡眠 sleep()

线程的睡眠即让当前正在运行的线程按照指定的时间暂停,并进入阻塞状态。

public class SleepDemo {
	public static void main(String[] args) {
		web12306 web=new web12306();
		
		Thread t1=new Thread(web,"路人甲");
		Thread t2=new Thread(web,"路人乙");
		Thread t3=new Thread(web,"路人丙");
		
		t1.start();
		t2.start();
		t3.start();
		
	}
}
class web12306 implements Runnable{
	private int num=50;
	@Override
	public void run() {
		while(true) {
			if(num<=0) {
				break;
			}
			try {
				Thread.sleep(1000);//线程睡眠  1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+"\t"+"剩余票数"+num--);
		}
	}
	
}
 

 

2、线程的礼让 yield()

线程的礼让即暂停当前运行的线程转为就绪状态并调用其它线程。

public class yieldDemo01 extends Thread{
	public static void main(String[] args) {
		yieldDemo01 demo=new yieldDemo01();//创建
		Thread t=new Thread(demo);//就绪
		t.start();
		 //cpu调度运行
		
		for(int i=0;i<300;i++) {
			 if(i%20==0) {
				 //暂停本线程  main
				 Thread.yield();
			 }
			 System.out.println("main........"+i);
		 }
		
	}
	@Override
	public void run() {
		for(int i=0;i<200;i++) {
			System.out.println("join........"+i);
		}
	}
}
 

 

 

3、线程的合并 join()

线程的合并即暂停当前的线程并执行调用join()方法的线程,直到执行结束当前线程才得以执行。

public class JoinDemo01 extends Thread{
	public static void main(String[] args) throws InterruptedException {
		 JoinDemo01 demo=new JoinDemo01();
		 Thread t=new Thread(demo);//新生
		 t.start();//就绪
		 //cpu调度运行
		 
		 for(int i=0;i<300;i++) {
			 if(i==50) {
				 t.join();//main 阻塞
			 }
			 System.out.println("main........"+i);
		 }
	}
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("join........"+i);
		}
	}
}
 

 

4、守护线程 setDaemon(true)

守护线程是为其他线程提供服务的,当前台线程结束生命周期后守护线程也会自动终止。

调用setDaemon(true)可以将指定的线程设置为守护线程。

public class Test {
	public static void main(String[] args) {
		MyThread myThread=new MyThread();
		for (int i = 0; i <100; i++) {
			System.out.println("main******"+i);
			if (i==30) {
				myThread.setDaemon(true);//设为守护线程	
				myThread.start();
			}
		}
	}
}

class MyThread extends Thread{
	
	@Override
	public void run() {
		for(int i=0;i<1000;i++) {//主线程结束后守护线程也会自动终止  由cpu调度决定不是实时的
			System.out.println("mythread-----"+i);
		}
		
	}
	
}
 

 

 

 


五、线程安全:

 

当多个线程共享一份资源时,由于cpu的调度的不确定性导致获取到的资源不一致,最后导致结果截然不同。所以为了避免出现这种情况就引入了线程安全。

 

线程同步:锁定共享的资源,每次只能让一个线程去执行,当这个线程执行完了,其他线程才能去执行。线程同步后效率会降低,但是线程会变得安全。


1、同步方法:在方法定义时加上synchronized 关键字,此方法即为同步方法。在调用该方法时会一步一步的执行方法体内的代码,直到执行完毕才会释放该方法,其他线程才能够访问该方法。

public synchronized void name() {
		//代码块
}
 

2、同步代码块:将需要锁定的代码放在同步块内。obj 为锁对象,一般选择共享资源对象作为锁对象,也可用this。

synchronized (obj) {
		//代码块
}
 

3、Lock互斥锁:创建一把锁,为需要锁定的代码加上一个锁,并在代码执行结束后释放锁。否则会造成死锁。

 

 Lock lock=new ReentrantLock();//创建锁
	
	public void test() {
		
		//上锁
		lock.lock();
		
		//代码块
		
		//解锁
		lock.unlock();
	}

 

 

 

水平有限,如有不足欢迎指出。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值