目录
线程
进程:指运行中的程序,进程是程序的一次执行过程(正在运行的一个程序)
线程:线程由进程创建,一个进程可以拥有多个线程
①.单线程:同一个时刻,只执行一个线程
②.多线程:同一个时刻,执行多个线程(同时下载歌曲、视频)
③.并发:同一个时刻,多个线程交替执行(开车时打电话,其实是大脑在切换)
④.并行:同一个时刻,多个线程同时执行(一边上厕所一边玩手机)
一.线程的使用
1.继承 Thread 类,重写 run() 方法
一个类继承 Thread 类,该类就可以当作线程使用,重写 run()方法
new App().new A().start();
for (int i = 5; i < 10; i++) {
System.out.print("11111" + "\t");
Thread.sleep(500);
}
}
class A extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("22222");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
输出:
2.实现 Runnable 接口 ,重写 run 方法
java 是单继承的,在某些情况下一个类可能已经继承了 一个 父类,这时再继承Thread 类显然是不可能的
实现 Runnable 接口的类实例化之后,是没有 start()方法的,需要创建一个 Thread 对象,
然后把 实现 Runnable 接口的类当作参数 传进去
Thread t = new Thread(new App().new A());
t.start();
for (int i = 0; i < 5; i++) {
System.out.print("11111" + "\t");
Thread.sleep(500);
}
}
class A implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("22222");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
输出:
二.线程的常用方法
1.setName()设置线程名称 |
2.getName()返回线程名称 |
3.setPriority()更改线程的优先级(范围在 1--10 ) ①.MIN_PRIORITY = 1 ②.NORM_PRIORITY = 5 ③.MAX_PRIORITY = 10 |
4.getPriority()获取线程的优先级 |
5.run()调用线程对象的 run()方法 |
6.start()是线程开始执行,调用 start0() |
7.slee()让指定的线程休眠 |
8.interrupt()中断线程(休眠中的线程) |
9.Thread.currentThread () 主线程 |
10.yield()礼让线程(时间不确定也不一定礼让成功) |
11.join()线程插队 |
1. 1--4
A a = new App().new A();
// 1.setName()设置线程名称
a.setName("张三");
// 2.getName()返回线程名称
System.out.println(a.getName());
// 3.setPriority()更改线程的优先级
a.setPriority(Thread.MIN_PRIORITY);
// 4.getPriority()获取线程的优先级
System.out.println(a.getPriority());
输出:
2. 5
调用 run()方法并不能实现多线程,它只能按顺序输出
A a1 = new App().new A();
// 5.run()调用线程对象的 run()方法
a1.run();
System.out.print(Thread.currentThread().getName() + "\t");
System.out.println("1000");
输出:
3. 6--9
A a1 = new App().new A();
// 6.start()是线程开始执行,调用 start0()
a1.start();
for (int i = 0; i < 5; i++) {
// 9.Thread.currentThread () 主线程
System.out.print(Thread.currentThread() + "\t");
System.out.println(i);
// 7.slee()让指定的线程休眠
Thread.sleep(1000);
}
// 8.interrupt()中断线程(休眠中的线程)
a1.interrupt();//打醒
}
class A extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.print(getName() + "\t");
System.out.println(i);
if (i == 2) {//休眠 20 秒
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
System.out.println("aaaaa");
}
}
}
}
}
输出:
4.10--11
start()调用了start0()
A a1 = new App().new A();
a1.start();
for (int i = 0; i < 5; i++) {
System.out.print(Thread.currentThread().getName() + "\t");
System.out.println(i);
if (i == 3) {
// 11.join()线程插队
a1.join();
}
}
}
class A extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.print(getName() + "\t");
System.out.println(i);
if (i == 1) {
// 10.yield()礼让线程(时间不确定也不一定礼让成功)
Thread.yield();
}
}
}
}
输出:
5.用户线程和守护线程
setDaemon() 设置守护线程
①.用户线程:也叫工作线程,当线程的任务执行完或通知结束
②.守护线程:为工作线程服务,当所有的工作线程结束 ,守护线程自动结束(垃圾回收机制为守护线程)
A a1 = new App().new A();
a1.setDaemon(true);
a1.start();
for (int i = 0; i < 2; i++) {
System.out.print(Thread.currentThread().getName() + "\t");
System.out.println(i);
}
}
class A extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.print(getName() + "\t");
System.out.println(i);
}
}
}
输出:
三.线程的状态
1.new:线程未开启时。创建线程对象没有 start()开始前
2.RUNNABLE:正在运行时。运行 strat 方法后
3.BLOCKED:阻塞状态,等待进入同步代码块的锁时
4.WAITING:等待状态。执行 wait()、join()、park()后
5.TIMED_WAITING:超时等待状态。WAITING 里方法加上sleep()
6.TERMINATED:终止状态(线程结束时)。线程运行完成、被打断、被中止
示意图:
四.Synchronized
1.线程同步机制
在多线程中,一些敏感数据不允许被多个线程同时访问,这时候就需要同步来保证数据在一个时刻只能由一个线程访问。
当有一个线程在对内存进行操作时,其他线程不可以对这个内存地址进行操作,直到这个线程完成操作,其他线程才可以进入
2.互斥锁
①.来保证共享数据的完整性
②.当某个对象用 Synchronized 修饰时,表面在同一时刻只能由一个线程访问
③.程序执行效率会变低
④.同步方法(非静态)的锁默认是 this ,也可以是其他对象
⑤.同步方法(静态的)的锁为当前类本身,类.class
同步方法
A a1 = new App().new A();
new Thread(a1).start();
new Thread(a1).start();
new Thread(a1).start();
}
class A implements Runnable {
private int j = 10;
boolean q = true;
public synchronized void a() {
if (j <= 0) {
q = false;
return;
}
System.out.print(Thread.currentThread().getName() + "\t");
System.out.println(j--);
}
@Override
public void run() {
while (q) {
a();
}
}
}
输出:
同步代码块
A a1 = new A();
new Thread(a1).start();
new Thread(a1).start();
new Thread(a1).start();
}
}
class A implements Runnable {
static private int j = 10;
static boolean q = true;
public static void a() {
synchronized (A.class) {
if (j <= 0) {
q = false;
return;
}
System.out.print(Thread.currentThread().getName() + "\t");
System.out.println(j--);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void run() {
while (q) {
a();
}
}
}
输出:
3.释放锁
释放锁的情况
①.当前线程的同步方法或同步代码块 :执行结束
②.当前线程的同步方法或同步代码块 :遇到 break、return
③.当前线程的同步方法或同步代码块 :出现了未处理的 Error 或 Exception,导致异常非正常结束
④.当前线程的同步方法或同步代码块 :执行了 wait(),线程暂停
不会释放锁的情况
①.线程执行同步方法或同步代码块时:程序调用了 sleep()、yield()方法,暂停当前线程
②.线程同步代码块时,其他线程调用了该线程的 suspend() 方法时该线程挂起
4.死锁
一个线程等待资源时,该资源被另一个线程所占用时,会导致死锁
new Thread(new A(true)).start();
new Thread(new A(false)).start();
}
}
class A implements Runnable {
static Object o1 = new Object();//静态成员是共享的
static Object o2 = new Object();
boolean b;
public A(boolean b) {
this.b = b;
}
@Override
public void run() {
if (b) {
synchronized (o1) {
System.out.println("o1");
synchronized (o2) {
System.out.println("o2");
}
}
} else {
synchronized (o2) {
System.out.println("o2");
synchronized (o1) {
System.out.println("o1");
}
}
}
}
}
卡死了(你先给我,不你先给我)
输出: