多线程(Java)

多线程

概念:

         1. 进程 ---> 指编写好的程序,在设备中运行起来后,所属的那片内存空间。

          2. 线程 ---> 指程序运行时,负责执行指令的执行器。

package com.evan.counter;

public class Test {

	public static void main(String[] args) {
		//以下代码是通过主线程来执行机器指令
		System.out.println("......");
		System.out.println("......");
		System.out.println("......");
		System.out.println("......");
		System.out.println("......");
		System.out.println("......");
	}

}

多线程则是指有多个指令执行器可以同时执行多段指令(代码)。

线程的创建:

          1. 继承Thread类,复写run方法。

package com.evan.counter;

public class Test {

	public static void main(String[] args) {
		MyThread thread = new MyThread();
		thread.start();
	}

}

class MyThread extends Thread{
	
	@Override
	public void run() {
		//要执行的代码
	}
}

2. 实现Runnable接口, 创建Thread,构造参数传入Runnable。

package com.evan.counter;

public class Test {

	public static void main(String[] args) {
		MyRunnable runnable = new MyRunnable();
		Thread thread = new Thread(runnable);
		thread.start();
	}

}

class MyRunnable implements Runnable{
	
	@Override
	public void run() {
		//要执行的代码
	}
}

线程和CPU之间的关系:

      CPU作为处理器,在一个时间段内只能处理一条线程,假设一个系统内开启了3条线程,那么CPU是在这3条线程之间做着随机切换,来保证多线程的“同时”执行。只是这个时间片很短。而让用户感觉不到。

线程状态:

  1. NEW(创建状态): 线程对象创建后的状态。
  2. RUNNABLE(可运行状态):在调用了Thread.start()之后,线程进入可运行状态,也就获取到了CPU的执行资格。
  3. RUNNING(运行状态) : 在获取到CPU执行资格之后,这时CPU也切换到了该线程上,就是运行状态。
  4. BLOCK(阻塞状态) : 在调用了thread.sleep或wait方法后,线程丧失CPU执行资格,进入阻塞状态。
  5. DESTORY(销毁状态) : 在调用了thread.destory()方法后,线程进入销毁状态。
  6. TERMINATED(结束状态) : 在线程的run方法运行完毕后,线程进入此状态。

多个线程访问多行代码涉及的问题:

先看一段示例代码

package com.evan.counter;


public class Test {

	public static void main(String[] args) {
		Resource resource = new Resource();
		MyRunnable runnable = new MyRunnable(resource);
		Thread t1 = new Thread(runnable);
		Thread t2 = new Thread(runnable);
		Thread t3 = new Thread(runnable);
		Thread t4 = new Thread(runnable);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}

class Resource{
	private int count = 100;
	
	public void mute() {
		if(count > 0) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			count--;
			System.out.println("Count: " + count);
		}
	}
	
}

class MyRunnable implements Runnable{
	private Resource resource;
	
	public MyRunnable(Resource resource) {
		super();
		this.resource = resource;
	}

	@Override
	public void run() {
		//要执行的代码
		while(true) {
			resource.mute();
		}
	}
}

运行结果有些意外,在我们进行count--操作前,我们已经进行了判断,if(count > 0),那为什么还会出现这样的情况。

这种情况就是因为CPU的随机切换造成的。

 结论就是: 如果有多个线程同时操作,多行代码,并且这多行代码都操作同一个变量时,就会造成这个问题。

解决办法:

我们如果想解决这个问题,就需要保证,在多行代码操作同一个变量时(区间内),保证只有一条线程进行操作,一条线程在操作的时候,其它线程就算切换到了RUNNING状态,也不能运行这多行代码。

这就涉及到了一个关键字,synchronized

synchronized关键字可以保证多行代码涉及到多线程时的执行问题,可以保证多行代码之间只允许一条线程执行,执行完毕后其它线程才可以继续执行。

我们修改一下Resource的代码,假如synchronized关键字

class Resource{
	private int count = 100;
	
	public void mute() {
		synchronized (Resource.class) {
			if(count > 0) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				count--;
				System.out.println("Count: " + count);
			}
		}
	}
	
}

现在运行结果已经正常了。

synchronized关键字的3种用法

前提: 使用synchronized关键字进行加锁时,需要保证多个线程之间使用的锁是同一把锁。

  1.  代码块 (同步代码块中放入显性的锁对象)
    class Resource{
    	private int count = 100;
    	
    	public void mute() {
    		synchronized (Resource.class) {
    			if(count > 0) {
    				try {
    					Thread.sleep(500);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				count--;
    				System.out.println("Count: " + count);
    			}
    		}
    	}
    	
    }

  2. 函数(同步函数使用的锁是this对象)

    class Resource{
    	private int count = 100;
    	
    	public synchronized void mute() {
    		if(count > 0) {
    			try {
    				Thread.sleep(500);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			count--;
    			System.out.println("Count: " + count);
    		}
    	}
    }

  3. 静态函数(静态同步函数使用的锁是当前对象的字节码对象)

    class Resource{
    	private static int count = 100;
    	
    	public static synchronized void mute() {
    		if(count > 0) {
    			try {
    				Thread.sleep(500);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			count--;
    			System.out.println("Count: " + count);
    		}
    	}
    }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值