JAVA线程基础笔记(自用)

                                                     **JAVA线程基础**

1,程序是为完成特定任务 用某种语言编写的一组指令的集合。 简单的说就是我们写的代码

2.进程是指运行中的程序 比如我们使用QQ 就启动了一个进程 操作系统会为其分配内存空间

进程是程序的依次执行过程,或是正在运行的一个程序 是动态的过程 有它自身的产生存在和消亡过程。

3.线程是由进程创建的,是进程的一个实体一个进程可以拥有多个线程 例如 迅雷下载多个任务
单线程:同一时刻 只允许执行一个线程
多线程 同一时刻 可以执行多个线程 比如qq打开多个聊天窗口

4.并发 同一个时刻 多个任务交替执行,造成一种“貌似同时”的错觉 简单来说 单核cpu实现的多任务就是并发

5.并行 同一个时刻 多个任务同时进行 。 多核cpu可以实现并行

用java 代码查看自己点脑的cpu 个数

Runtime r =Runtime.getRuntime();
		int  cpu= r.availableProcessors();  //获取当前电脑的CPU个数
		
		System.out.println(cpu);

线程的基本使用

创建线程的两种方法

1.继承Thread类 重写run方法( 一个类只能继承一个父类 所以有局限性)
当一个类继承了Thread 类 该类就可以当作线程使用
重写run方法 写自己的业务代码
run Thread类 实现了Runnable 接口的run 方法
当程序启动时 会调用主线程 当启动一个子线程后 主线程不会阻塞会继续执行 这时主线程和子线程交替执行
主线程结束不一定进程结束

t.start()启动线程 如果直接调用 run 方法 相当于时main 线程调用的run 方法 这样必须执行完程序才能往下进行运行
Thread.sleep(1000); 休眠 单位毫秒

Thread.currentThread().getName(); 获取线程名

2.实现Runnable 接口 重写 run方法

实现 run 接口 Runnable 没有start 方法 也不能直接调用 run方法

package Test;

public class d implements Runnable{

	@Override
	public void run() {			
		while(true)
		{
			System.out.println("祥哥好帅");
			
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	             Thread.currentThread().getName();     
		}
		     		
	}
	


}
package Test;

public class Test {
 public static void main(String[] args) {
	 //创建一个 线程
//	 Thread01 t =new Thread01();
//	//启动线程
//	 t.start();
	 
	    d  D=new d();
	 Thread t =new Thread(D);
	
	 t .start();
	 
	 
}
}

继承Thread 和 实现Runnable 的区别

1.从java 的设计来看 通过继承Thread 或者实现Runnable 接口来创建线程本质上没有区别 Thread 类本身就是西安了Runnable 接口

2.实现Runnable 接口方式更加适合多个线程共享一个资源的情况并且避免了单继承的限制

线程终止
1,当线程完成任务后,会自动退出
2.还可以通过使用变量来控制run方法退出的方式停止线程 即通知方法

线程常用方法
Thread.currenTread().getName() 获取当前线程的名称

1.setName 设置线程名称

2.getName 返回该线程的名称

3.statr 使线程开始执行

4.run 调用线程对象

5.getPriority 更改线程的优先级

6.getPriority 获取线程的优先级

7.sleep 休眠线程

8.interrupt 中断线程 但并没有结束线程 所以一般用于中断正在休眠的线程 一般用于中断休眠的线程

9.yield 线程的礼让 让出cpu 让其他线程执行 但礼让的时间不确定 所以不一定能礼让成功

10 join 线程的插队 插队的线程一旦插队成功 则肯定先执行完插入的线程所有的任务

11 setDaemon(true); 守护线程 在启动线程前使用

当线程执行到一个interrupt 方法时就会catch(try ccatch 里面的) 一个异常(InterruptedException e) 可以加入自己的业务代码

使用多线程进行售票模拟 会发现程序会出现超卖 和卖同一张票的情况

用户线程 和守护线程

用户线程 也叫工作线程,当线程的任务执行完或通知方式结束

守护线程 一般是为工作线程服务的当所有的用户线程结束守护线程自动结束 (比如我想要主线程结束时不管子线程结束没结束 都得停止执行 只需将子线程设置成守护线程)
myDaemonThread.setDaemon(true);

常见的守护线程 垃圾回收机制

线程的生命周期

在这里插入图片描述

1.新建状态(new):使用new创建一个线程对象,仅仅在堆中分配内存空间,在调用start方法之前的线程所处的状态;在此状态下,线程还没启动,只是创建了一个线程对象存储在堆中;比如:

Thread t = new Thread(); // 此时t就属于新建状态

当新建状态下的线程对象调用了start方法,该线程对象就从新建状态进入可运行状态(runnable);线程对象的start方法只能调用一次,多次调用会发生IllegalThreadStateException;

2.可运行状态(runnable):又可以细分成两种状态,ready和running,分别表示就绪状态和运行状态。

就绪状态:线程对象调用start方法之后,等待JVM的调度(此时该线程并没有运行),还未开始运行;
运行状态:线程对象已获得JVM调度,处在运行中;如果存在多个CPU,那么允许多个线程并行运行;
3.阻塞状态(blocked):处于运行中的线程因为某些原因放弃CPU时间片,暂时停止运行,就会进入阻塞状态;此时JVM不会给线程分配CPU时间片,直到线程重新进入就绪状态(ready),才有可能转到运行状态;

阻塞状态只能先进入就绪状态,进而由操作系统转到运行状态,不能直接进入运行状态;阻塞状态发生的两种情况:

当A线程处于运行中,试图获取同步锁时,但同步锁却被B线程获取,此时JVM会把A线程存到共享资源对象的锁池中,A线程进入阻塞状态;
当线程处于运行状态,发出了IO请求时,该线程会进入阻塞状态;
4.等待状态(waiting):运行中的线程调用了wait方法(无参数的wait方法),然后JVM会把该线程储存到共享资源的对象等待池中,该线程进入等待状态;处于该状态中的线程只能被其他线程唤醒;

5.计时等待状态(timed waiting):运行中的线程调用了带参数的wait方法或者sleep方法,此状态下的线程不会释放同步锁/同步监听器,以下几种情况都会进入计时等待状态:

当处于运行中的线程,调用了wait(long time)方法,JVM会把当前线程存在共享资源对象等待池中,线程进入计时等待状态;
当前线程执行了sleep(long time)方法,该线程进入计时等待状态;
6.终止状态(terminated):也可以称为死亡状态,表示线程终止,它的生命走到了尽头;线程一旦终止,就不能再重启启动,否则会发生IllegalThreadStateException;有以下几种情况线程会进入终止状态:

正常执行完run方法而退出,寿终正寝,属于正常死亡;
线程执行遇到异常而退出,线程中断,属于意外死亡;
在这里插入图片描述

线程同步机制 Synchronized

1.在多线程编程 一些敏感数据不允许被多个线程同时访问,此时就是用同步访问技术 保证数据在任何时刻 最多有一个线程访问 以保证数据的完整性
2.也可以理解 线程同步 即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作 直到该线程完成操作 其他线程才能对该内存地址进行操作。

3 操作同步代码时 只能有一个线程参与 其他线程等待 相当于是一个单线程的过程 效率低。

同步具体方法-Synchronized

1.同步代码块
synchronized (同步监视器){ //得到对象的锁才能操作同步代码
//需要被同步的代码 (不能包多也不能包少了 )

}
说明: 操作共享数据的代码即为需要被同步的代码
共享数据: 多个线程共同操作的数据
同步监视器 :俗称 锁 任何一个对象的数据 都可以当锁
要求:多个线程必须要共用一把锁 唯一性
实现接口可以用this 继承可以用 类.class

2.synchronized 还可以放在方法生命中 表示整个方法为同步方法

如果要共享数据的代码完整的声明在一个方法中 我们可以把此方法声明为同步的

public synchronized void m (String name ){//需要被同步的代码

}

关于同步方法的总结
1.同步方法仍然设计到同步监视器,只是不需要我们显式声明
2.非静态的同步方法 同步监视是: this
静态的同步方法 同步监视器是当前类本身

线程的死锁
基本介绍 : 多个线程都占用了对方的锁资源但不肯相让 导致了死锁 在编程时一定要避免死锁的发生

释放锁
1.当线程的同步方法,同步代码块执行结束
2.当线程在同步代码块 同步方法中遇到break return
3.当线程在同步代码块 同步方法中出现了未处理的Error 或Exception导致异常结束
4.当线程在同步代码块 同步方法中执行了线程对象的wait()方法 当前线程暂停 并释放锁

下面操作不会释放锁
1.线程执行同步代码块或同步方法时 程序调用Thread.sleep() Thread.yield() 方法暂停当前的线程的执行不会释放锁
2.线程执行同步代码块时 其他线程调用了该线程的suspend()方法将该线程挂起 改线程不会释放锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值