线程的概念以及用java实现线程

线程与进程

进程:每个进程都有独立的内存空间,一个进程可以看做是一个软件或应用程序
线程:是进程中的多个执行路径,线程可以看作是软件里的执行路径。每个线程都有自己的栈空间,共用一个堆内存。由一个线程调用的方法,那么这个方法也在这个线程内执行

线程的一些概念:

线程的调度:

分时调度
抢占式调度(java中使用的是抢占式调度)

线程的分类:

线程分为守护线程和用户线程

  • 守护线程:守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡。(可以使用t1.setDaemon(true)将线程设置为守护线程)
  • 用户线程:当一个进程不包含任何用户线程时,进程结束
线程的状态
  1. 新建(new):先创建的线程对象
  2. 可运行(就绪)(runnable):线程创建后,被其他线程调用了该线程的start()方法。该状态的线程位于可运行线程池中,等待cpu (处理机)的使用权 。
  3. 运行)(running):可运行状态的线程获得了cpu (处理机)时间片,开始执行程序代码。
  4. 阻塞(blocked):线程因为某种原因主动放弃了cpu 使用权,暂时停止运行。直到线程完成了需要等待的操作,才会转为就绪状态,再次争夺cpu使用权。
    1. 死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
同步与异步:

同步:排队执行,效率低,但是安全
异步:同时执行,效率高,但是数据不安全
什么是数据的安全和不安全?举个例子:

public class Demo1{
	public static void main(String[] args){
		Runnable run = new Ticket();
		//让3个线程一起卖票
		new Thread(run).start();
		new Thread(run).start();
		new Thread(run).start();
	}
	static class Ticket implements Runnable{
		//票数
		private int count = 10;
		public void run(){
			while(count>0){
				//卖票
				System.out.println("准备卖票");
				count--;
				System.out.println("出票成功,余票:"+count);
			}
		}
	}
}

这段代码多次运行测试后,会出现如下情况:
在这里插入图片描述
我们发现,余票出现了-1,但并不是每次都会出现-1。出现这种情况的原因是:当第一个count减到1的线程运行到count减1时,此时count还没有减1,但是其他两个线程已经到了while循环,判断count大于0,成功进入循环,继续向下执行就导致了出现count小于0 的情况。线程执行的顺序并不是固定的,所以要多次执行会出现这种情况,并不是每次都会出现。
线程不安全的解决方案:
隐式锁:

  • 同步代码块:synchronized(锁对象){代码块}//锁对象就是一个Object类型的变量,相同变量是一个锁。看同一把锁才能排队。
  • 同步方法:在方法前加上synchronized修饰,进行排队
    public synchronized boolean fangFaMing(){}

显示锁:

  • 显示锁Lock子类 ReentrantLock
    Lock l = new ReentrantLock();
    ……
    l.lock();
    ……
    l.unlock();
并发与并行

并发:指两个或者多个事件在同一时间段内发生
并行:至两个或者多个事件在同一时刻发生(同时发生)

如何用java实现线程

实现方法:
  1. 实现Runnable接口
  • 通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行相同任务的情况。
  • 可以避免单继承所带来的的局限性(在java中,一个子类只能继承一个类,但是可以实现多个接口)
  • 任务与线程本身是分离的,提高了程序的健壮性
  1. 继承Thread类
    能够通过使用匿名内部类的方式简便地生成线程

创建好线程类之后,在方法中调用start()方法就可以实现一个新的线程了

Thread类中的方法:
  • 已过时的方法:
    stop():本质上是不安全的,如果一个正在执行的线程,它还在占用着资源,如果直接停止,可能会导致其所占用的资源无法释放,正确的停止方法是通知线程该结束了,让他return run()方法可以通过变量做标记的方式通知。
  • 常用方法:
  1. 构造方法:
    Thread()
    Thread(Runnable target)指定线程所要做的任务
    Thread(Runnable target,String name)指定线程所要做的任务,并且给他起一个名字
    Thread(String name)传给线程所要做的任务名
  2. String getName() 返回线程的名称
  3. long getId() 返回线程的标识符
  4. int getPriority() 返回线程的优先级
  5. void setPriority(int newPriority)设置线程的优先级
  6. void start() 让线程开始执行,java虚拟机调用此线程的run方法
  7. void sleep(long millis)参数:毫秒。为当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性 进程执行时,遇到sleep就会休眠,休眠具体时长就是传入的参数,休眠结束才回继续向下执行,可以用于让程序每隔几秒输出一个东西
  8. void sleep(long millis,int nanos)参数:毫秒,纳秒。指定毫秒数加上纳秒数
  9. void setDaemon(boolean on) 将此线程标记为daemon线程(守护线程)或者用户线程main方法线程为主线程,从其他方法开启的线程叫子线程
设置和获取线程的名称

可以使用Thread.currentThread()获取当前正在运行的线程
创建线程的默认名称是Thread-0,Thread-1,Thread-2……
在创建时传入名称就可以设置线程的名称:
New Thread(new myRunnable(),”名称”);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值