多线程初体验

一、什么是多线程

进程:应用程序执行实例
线程:进程中执行运算的最小单元

如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”
多个线程交替占用CPU资源,而非真正的并行执行

多线程好处
充分利用CPU的资源
简化编程模型
带来良好的用户体验

同步和异步
同步是阻塞模式,一个进程执行一个线程,需等待这个线程结束,才能执行下一个线程,否则只能一直等待
异步是非阻塞模式,一个进程执行一个线程,若这个线程未完成,仍能执行另外的线程,相互之间互不影响

二、线程的状态(生命周期)

共分为五个状态:创建状态、就绪状态、阻塞状态、运行状态、死亡状态
线程的状态

三、创建线程的方式

(1)继承java.lang.Thread类

public class MyThread extends Thread{	
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
}

public class MyThreadTest {
	public static void main(String[] args) {
		MyThread thread1 = new Mythread();
		MyThread thread2 = new Mythread();
		
		thread1.start();
		thread2.start();
	}
}

(2)实现java.lang.Runnable接口

public class MyRunable implements Runnable{
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
}
public class RunableTest {
	public static void main(String[] args) {
		MyRunable r1 = new MyRunable();
		MyRunable r2 = new MyRunable();
		Thread thread1 = new Thread(r1);
		Thread thread2 = new Thread(r2);
		
		thread1.start();
		thread2.start();
	}
}

注意:
(1)多个线程交替执行,不是真正的“并行”
(2)线程每次执行时长由分配的CPU时间片长度决定
(3)main方法会启动一个主线程,也叫守护线程

两种创建线程的方式的区别:

(1)继承Thread类
编写简单,可直接操作线程
适用于单继承

(2)实现Runnable接口
避免单继承局限性
便于共享资源

线程中比较run()和start()两者的区别
(1)单独调用run()就是普通方法,跟线程无关
(2)调用start()方法会启动一个线程

四、线程的常用方法

(1)void setPriority(int newPriority) 更改线程的优先级
线程的优先级的范围是:1~10,1为最低,线程包括主线程的默认优先级都为5;
优先级只表示线程获得CPU资源的概率大小,并不代表不会运行

(2)static void sleep(long millis) 线程休眠指定毫秒数,参数为毫秒
线程休眠是让线程进入阻塞状态,休眠时间过去线程进入就绪状态,重新运行

(3)void join() 中断正在运行的线程,执行join 的线程,直到该线程全部运行完毕,再执行其他未完成的线程

(4)static void yield() 线程礼让
该线程处于就绪状态,不转为阻塞状态
暂停当前线程,允许其他具有相同优先级的线程获得运行机会,但只是允许,让不让看心情,并不绝对

(5)void interrupt() 线程中断,中断当前线程的阻塞状态

	// 中断线程
	Thread.currentThread().interrupt();
	//给线程打上中断标签
	Thread.currentThread().interrupted();
	//判断线程是否中断
	Thread.currentThread().isInterrupted();

(6)boolean isAlive () 测试线程线程是否处于活动状态

(7)void notify() 唤醒当前线程

(8)void notifyAll() 唤醒所有线程

(9)void wait() 让当前线程进入阻塞状态,同时释放当前线程所持有的锁
void wait(long millis) 线程等待指定时间,自动被唤醒

synchronized(),wait(),notify() 对象一致性,wait和notify方法都应该在synchronized中使用

五、共享数据引起的并发问题

多个线程共享一个数据会引起并发问题

public class Site implements Runnable {
	// 记录剩余的票数
	private int count = 10; 
	// 记录买到第几张
	private int num = 0; 

	@Override
	public void run() {
		while (true) {
		synchronized (this) {
			if (count <= 0) {
				break;
			}
			count--;
			num++;
		}
			System.out.println(Thread.currentThread().getName() + "抢到第" + num + "张票,剩余" + count + "张票!");
		}
	}
}


public class Test {
	public static void main(String[] args) {
		Site site = new Site();
		Thread t1 = new Thread(site,"黄牛党");
		Thread t2 = new Thread(site,"抢票代理");
		Thread t3 = new Thread(site,"张三");
		System.out.println("**********开始抢票**************");
		t1.start();
		t2.start();
		t3.start();
	}
}

使用synchronized
(1)锁对象,所代码块本质上也是锁对象
多个并发线程访问同一资源的同步代码块时,同一时刻只能有一个线程进入synchronized(this)同步代码块
当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码块

(2)锁方法

线程安全的效率
当使用锁时,线程安全,但因为多个线程共享一把锁,会造成效率较低

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值