一、线程
1.并发与并行
并发:在同一时间段 单核CPU交替的执行
并行:在同一时刻 多核CPU同时的执行
2.进程与线程
进程:运行在内存中存储
线程:通向CPU的执行的路径 单线程和多线程
3.主线程
4.第一种创建线程的方式
继承Thread
1.定义一个类继承Thread
2.重写run方法
3.实例化线程对象
4.开启线程 调用start方法
5.线程调度方式
线程调度方式:分配式调度与抢占式调度
java就是典型的抢占式调度
6.抢占式调度原因
7.线程内存图
二、线程常用的方法
1.获取线程名称
getName() 返回线程的名称
Thread.currentThread() 返回当前线程
2.设置线程名称
setName(String name)通过方法设置线程名称
public Thread(String name) 通过构造方法设置线程名称
3.线程休眠
Thread.sleep(long millis)
4.守护线程
守护其他线程完成操作 协助其他线程 java中垃圾回收期(GC)就是一个守护线程
守护线程的死亡:被守护的线程执行完线程操作 或者是被守护线程死亡了
5.设置和获取线程的优先级
5.1常量
5.2方法
注意点:线程设置优先级越高 获取CPU执行权机会更大 并不一定会优先执行
6.线程第二种创建方式
实现Runnable接口
1.定义一个类实现Runnable接口
2.重写抽象方法run()
3.实例化实现类对象
4.实例化Thread,并将实现类对象传入Thread构造方法中
5.开启线程,调用start()
package com.qf.stu.demo4;
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
package com.qf.stu.demo4;
public class Test {
public static void main(String[] args) {
MyRunnable myrun=new MyRunnable();
Thread th=new Thread(myrun);
th.start();
}
}
7.使用内部类的方式来创建线程
package com.qf.stu.demo4;
public class Test1 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
},"线程一").start();
new Thread("线程二"){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
}
}
三、线程通信
解决线程不安全的方法
1.同步代码块
synchronized(锁对象){
可能产生线程安全的代码块
}
说明:锁对象可以是任意的对象 所有线程的锁的对象必须是同一个对象
package com.qf.stu.demo6;
public class MyRunnable implements Runnable {
private int tik=100;
Object obj=new Object();
@Override
public void run() {
while (true){
synchronized (obj){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (tik>0){
System.out.println(Thread.currentThread().getName()+"\t"+"第"+tik+"张票");
tik--;
}
}
}
}
}
2.同步方法
访问修饰符 synchronized 返回值类型 方法的名称(参数列表){
可能产生问题的代码
}
说明 synchronized可以修饰成员方法 锁的对象就是当前对象
也可以修饰静态方法 锁的对象是当前对象的Class对象
package com.qf.stu.demo6;
public class MyRunnable implements Runnable {
private int tik=100;
Object obj=new Object();
@Override
public void run() {
while (true){
show();
//synchronized (obj){
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// if (tik>0){
// System.out.println(Thread.currentThread().getName()+"\t"+"第"+tik+"张票");
// tik--;
// }
// }
}
}
public synchronized void show(){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (tik>0){
System.out.println(Thread.currentThread().getName()+"\t"+"第"+tik+"张票");
tik--;
}
}
}
3.第三种解决方案Lock
1.Lock实现提供了比使用 synchronized方法和语句可获得的更广泛的锁定操作,此实现允许更灵活的结构
提供了两个方法
lock()获取锁对象
unlock()释放锁对象
实例化 ReentranLock
package com.qf.stu.demo7;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyRunnable implements Runnable {
private int tik=100;
Lock l=new ReentrantLock();
@Override
public void run() {
while (true){
l.lock();
try {
Thread.sleep(50);
if (tik>0){
System.out.println(Thread.currentThread().getName()+"\t"+"第"+tik+"张票");
tik--;
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
l.unlock();
}
}
}
}
四、死锁
死锁:A占用B的锁对象 B占用A的锁对象 A、B互不谦让 A与B出现同时等待的状态