线程第一篇

一、概念

       进程:进程是指正在运行的程序。确切的说,当一个程序进入内存中运行时即变成一个进程。

        

      线程:线程是进程中的一个执行单元,负责当前进程中程序的执行。一个进程至少有一个线程。

      多线程:一个程序中多个线程同时进行。

       

所以,一个电脑的快慢决定于CPU和内存,因为软件都是在内存中运行的。

二,程序运行原理

l 分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

l 抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

三、线程状态

四、如何创建线程

        1,继承Thread类      

             1 定义一个类继承Thread。

             2 重写run方法。(run方法里写的就是线程任务)

             3 创建子类对象,就是创建线程对象。

             4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。

 

        2,实现Runnable接口并重写run方法,start()方法调用(run方法里写的就是线程任务)     

             1、定义类实现Runnable接口。

             2、覆盖接口中的run方法。。

             3、创建Thread类的对象

             4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。

             5、调用Thread类的start方法开启线程。

       3,实现Callable<v>接口并重写call()方法(和run方法功能一样,但该方法有返回值,且会抛异常)

       获取线程名方法:Thread.currentThread().getName()

五、线程池

             如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的         效率,因为频繁创建线程和销毁线程需要时间。

       Executors:线程池创建工厂类

      public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象

      ExecutorService:线程池类

      简单代码演示:

     //创建线程池对象

      ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象

     //创建Runnable实例对象

      MyRunnable r = new MyRunnable();

      //从线程池中获取线程对象,然后调用MyRunnable中的run()

      service.submit(r);//每submit一次获取个线程去执行任务

     //再获取个线程对象,调用MyRunnable中的run()

     service.submit(r);

      //关闭线程池

      service.shutdown();

如果有兴趣的可以参考:https://blog.csdn.net/weixin_28760063/article/details/81266152

六、多线程的安全问题

       1.1,多个线程运行同一段代码,共享一个资源,这是就会出现线程安全问题。

       案例:电影院卖票,一共100张。假设有三种方式购买(美团、淘票票、现场排队),相当于三个线程共同操作这100张票,这时就会出现线程安全问题。

七,解决线程安全问题         

     2.1 线程同步(线程安全处理synchronized)   

  

上图中使用了synchronized(obj)同步代码块,起锁对象可以使任意对象。也可以用同步方法

public synchronized void method(){

if (ticket > 0) {

//模拟选坐的操作

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

其所对象是this

还可以用静态方法,其锁对象是该类.class (属性)

System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);

     2.2使用Lock接口解决线程安全问题

public class Ticket implements Runnable {

//共100票

int ticket = 100;

//创建Lock锁对象

Lock ck = new ReentrantLock();

@Override

public void run() {

while(true){

//synchronized (lock){

//获取锁

ck.lock();

if (ticket > 0) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);

}

//释放锁

ck.unlock();

总结,该方式可以每次释放锁,而synchronized 方式只有出了同步方法才会释放,如果出异常catch后不会释放锁

七,死锁

         同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉。

死锁情况代码演示:

  1 定义锁对象类

public class MyLock {
	public static final Object lockA = new Object();
	public static final Object lockB = new Object();
}

 2 线程任务类

public class ThreadTask implements Runnable {
	int x = new Random().nextInt(1);//0,1
	//指定线程要执行的任务代码
	@Override
	public void run() {
		while(true){
			if (x%2 ==0) {
				//情况一
				synchronized (MyLock.lockA) {
					System.out.println("if-LockA");
					synchronized (MyLock.lockB) {
						System.out.println("if-LockB");
						System.out.println("if大口吃肉");
					}
				}
			} else {
				//情况二
				synchronized (MyLock.lockB) {
					System.out.println("else-LockB");
					synchronized (MyLock.lockA) {
						System.out.println("else-LockA");
						System.out.println("else大口吃肉");
					}
				}
			}
			x++;
		}
	}
}

 3 测试类

public class ThreadDemo {
	public static void main(String[] args) {
		//创建线程任务类对象
		ThreadTask task = new ThreadTask();
		//创建两个线程
		Thread t1 = new Thread(task);
		Thread t2 = new Thread(task);
		//启动线程
		t1.start();
		t2.start();
	}
}

八,线程常用方法

1 sleep():休眠一定时间后又开始抢夺CPU资源执行任务

2 wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。在没有notify()唤醒之前永久等待

3 notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。

4 notifyAll():唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

注意:2,3,4这三个方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程(必须用锁对象去调用)。这三个方法并不定义在 Thread中,也没定义在Runnable接口中,却被定义在了Object类中,因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值