package com.qf.test.test01;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=30;i>0;i--){
System.out.println("班长,他还有"+i+"秒就...");
try {
MyThread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.qf.test.test01;
public class Test01 {
public static void main(String[] args) {
MyThread th = new MyThread();
th.start();
}
}
守护线程:
简介:
守护其他线程,守护其他线程执行操作 在java中gc就是一个守护线程,在项目运行中会产生很多垃圾,这些垃圾都会被gc默默回收
守护线程的死亡:被守护的线程完成操作
被守护线程死亡
守护线程默认守护的是主线程 守护线程的方法:
package com.qf.test.test02;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class MyThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(5000);
Writer w = new FileWriter("2.txt");
w.write("搞定");
w.close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.qf.test.test02;
public class Test {
public static void main(String[] args) {
//实例化线程对象
MyThread th = new MyThread();
//将线程设为守护线程
th.setDaemon(true);
//判断是否是守护线程
System.out.println(th.isDaemon());
//开启线程
th.start();
try {
//将主线程睡眠
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
线程的优先级:
注意点:
线程的优先级范围是1-10
线程优先级默认值是5
常量:设置优先级的方法:
注意点:线程优先级越高,表示获取CPU执行权力越大,但不一定表示一定优先执行,只是优先执行的概率大,因为java中多线程是抢占式分配
二、第二种创建线程的方法步骤:
1.创建一个类实现Runable接口
2.实现run方法
3.实例化线程对象Thread 构造方法中传入Runable的实现类对象
4.开启线程
代码:
package com.qf.test.test03;
public class MyRunable implements Runnable{
@Override
public void run() {
for (int i=1;i<11;i++){
System.out.println(Thread.currentThread().getName()+"t"+i);
}
}
}
package com.qf.test.test03;
public class Test {
public static void main(String[] args) {
//实例化线程对象
Thread th = new Thread(new MyRunable());
th.start();
Thread th2 = new Thread(new MyRunable());
th2.start();
}
}
三、使用匿名类创建线程
package com.qf.test.test04;
public class Test {
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(getName());
}
}.start();
}
}
四、线程通信
案例:
需求:
分析:
代码:
package com.qf.test.test05;
public class MyRunabel implements Runnable{
private int count =100;
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true){
if (count>0){
System.out.println(Thread.currentThread().getName()+"正在售卖第"+count+"张票");
count--;
}
}
}
}
package com.qf.test.test05;
public class Test {
public static void main(String[] args) {
//实例化MyRunable对象
MyRunabel run = new MyRunabel();
//实例化线程对象
Thread th01 = new Thread(run);
th01.start();
//实例化线程对象
Thread th02 = new Thread(run);
th02.start();
//实例化线程对象
Thread th03 = new Thread(run);
th03.start();
}
}
会产生的问题:
1.售卖重复的票 2.售卖不存在的票
产生问题的原因: 第一种解决的方法-使用同步代码块 语法:synchronized(锁的对象){
可能产生数据共享安全问题代码
}
说明:A.锁的对象可以是任意对象
B.所有的线程必须是操作同一锁的对象才能保证数据共享安全
作用:解决多线程数据共享安全的问题
代码:
package com.qf.test.test06;
public class MyRunable implements Runnable{
private int count=100;
//定义一个对象
private String s = new String();
@Override
public void run() {
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//使用同步代码块解决
synchronized (s){
if (count>0){
System.out.println(Thread.currentThread().getName()+"正在售卖第"+count+"张票");
count--;
}
}
}
}
}
package com.qf.test.test06;
public class Test {
public static void main(String[] args) {
//实例化Runable对象
MyRunable run = new MyRunable();
//实例化线程对象
Thread th01 = new Thread(run);
th01.start();
//实例化线程对象
Thread th02 = new Thread(run);
th02.start();
//实例化线程对象
Thread th03 = new Thread(run);
th03.start();
}
}
解决问题的原理:
第二种解决问题的方法-使用同步方法
语法:
访问修饰符 synchronized 返回值类型 方法的名称(参数列表) {
方法体;
return 返回值
}
说明:synchronized 可以修饰普通成员方法 也可以修饰静态方法
注意点:普通成员方法锁的对象是当前对象this
静态方法锁的对象是当前对象的class对象
代码: 普通方法package com.qf.test.test06;
public class MyRunable01 implements Runnable {
private int count =100;
@Override
public void run() {
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//show();
//这样写和同步方法效果一样
synchronized (this){
if (count>0){
System.out.println(Thread.currentThread().getName()+"正在售卖第"+count+"张票");
count--;
}
}
}
}
//利用同步方法
}
package com.qf.test.test06;
public class Test01 {
public static void main(String[] args) {
//实例化Runable对象
MyRunable01 run = new MyRunable01();
//实例化线程对象
Thread th01 = new Thread(run);
th01.start();
//实例化线程对象
Thread th02 = new Thread(run);
th02.start();
//实例化线程对象
Thread th03 = new Thread(run);
th03.start();
}
}
代码- 静态方法:
package com.qf.test.test06;
public class MyRunable02 implements Runnable {
private static int count=100;
@Override
public void run() {
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//show();
//这样写和同步静态方法效果一样
synchronized (MyRunable02.class){
if (count>0){
System.out.println(Thread.currentThread().getName()+"正在售卖第"+count+"张票");
count--;
}
}
}
}
//利用同步静态方法
}
package com.qf.test.test06;
public class Test02 {
public static void main(String[] args) {
//实例化Runable对象
MyRunable02 run = new MyRunable02();
//实例化线程对象
Thread th01 = new Thread(run);
th01.start();
//实例化线程对象
Thread th02 = new Thread(run);
th02.start();
//实例化线程对象
Thread th03 = new Thread(run);
th03.start();
}
}
第三种解决的方法-Lock
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的 结构
实现类:ReentrantLock类 方法:代码:
package com.qf.test.test06;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyRunnable implements Runnable {
private int count =100;
//实例化Lock对象
private Lock l = new ReentrantLock();
@Override
public void run() {
while (true){
//调用锁
l.lock();
try {
Thread.sleep(50);
if (count>0){
System.out.println(Thread.currentThread().getName()+"正在售第"+count+"张票");
count--;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
l.unlock();
}
}
}
}
package com.qf.test.test06;
public class Test03 {
public static void main(String[] args) {
//实例化Runnable对象
MyRunable run = new MyRunable();
//实例化线程对象
Thread th = new Thread(run);
th.start();
//实例化线程对象
Thread th1 = new Thread(run);
th1.start();
//实例化线程对象
Thread th2 = new Thread(run);
th2.start();
}
}
五、死锁
概念:
A占用B锁的锁对象 B占用A锁对象 互不相让 两个线程处于等待状态 这样就出现了死锁
六、线程中常用方法(面试会问) stop 方法演示package com.qf.test.test07;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i<10;i++){
//判断
if (i==5){
//终止线程
//stop();
//终止线程 但是是等线程执行完操作后才终止
interrupt();
}
System.out.println(getName()+"t"+i);
}
}
}
package com.qf.test.test07;
public class Test01 {
public static void main(String[] args) {
//实例化线程对象
MyThread th1 = new MyThread();
th1.start();
}
}
yield() 方法演示
package com.qf.test.test08;
public class MyThread extends Thread{
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println(getName()+"t"+i);
}
}
}
package com.qf.test.test08;
public class Test {
public static void main(String[] args) {
//实例化线程对象
MyThread th1 = new MyThread();
//礼貌性谦让
Thread.yield();
//开启线程
th1.start();
//实例化线程对象
MyThread th2 = new MyThread();
//开启线程
th2.start();
}
}
join() 方法演示
package com.qf.test.test09;
public class MyThread extends Thread{
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println(getName()+"t"+i);
}
}
}
package com.qf.test.test09;
public class Test {
public static void main(String[] args) throws InterruptedException {
//实例化线程对象
MyThread th1 = new MyThread();
//开启线程
th1.start();
//等线程一先执行完 线程二在开始执行
th1.join();
//实例化线程对象
MyThread th2 = new MyThread();
//开启线程
th2.start();
}
}
七、Object提供操作线程的方法
案例:
需求:
代码:
package com.qf.test.test11;
public class Test {
public static void main(String[] args) {
//创建一个对象
String s= new String();
//创建班长线程
new Thread(){
@Override
public void run() {
//上锁
synchronized (s){
System.out.println("班长要一个技师按摩");
try {
//进入无限等待
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("班长正在享受按摩.....");
}
}
}.start();
//创建按摩店线程
new Thread(){
@Override
public void run() {
//上锁
synchronized (s){
//叫技师需要两秒
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("老板说:技师到位");
//唤醒班长
s.notify();
}
}
}.start();
}
}
八、多线程中生产者与消费者模式
需求:
代码-生产者线程
package com.qf.test.test12;
public class MyThread01 extends Thread {
//声明一个包子对象
private BaoZi baoZi;
//通过构造方法给包子对象赋值
public MyThread01(BaoZi baoZi){
this.baoZi=baoZi;
}
//重写run方法
@Override
public void run() {
//要一直生产包子 使用死循环
while (true){
//给包子对象加锁
synchronized (baoZi){
//判断是否有包子
if (baoZi.flag){
//有包子就进行等待
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没有包子就需要生产包子
baoZi.pi="冰皮";
baoZi.xian="绿豆沙";
System.out.println("生产了一个"+baoZi.pi+baoZi.xian+"的包子");
//将标记改为true
baoZi.flag=true;
//通知消费者消费
baoZi.notify();
}
}
}
}
代码-消费者线程
package com.qf.test.test12;
public class MyThread02 extends Thread {
//声明一个包子对象
private BaoZi baoZi;
//通过构造方法给包子对象赋值
public MyThread02(BaoZi baoZi){
this.baoZi=baoZi;
}
//重写run方法
@Override
public void run() {
//要一直消费包子 使用死循环
while (true){
synchronized (baoZi){
//判断是否有包子
if (!baoZi.flag){
//没有包子 要等待
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//消费包子
System.out.println("消费了一个"+baoZi.pi+baoZi.xian+"的包子");
//将包子的属性设置为空
baoZi.pi=null;
baoZi.xian=null;
//将标记改为false
baoZi.flag=false;
//通知生产者生成包子
baoZi.notify();
}
}
}
}
代码-包子类
package com.qf.test.test12;
public class BaoZi {
public String pi;
public String xian;
public boolean flag = false;//默认没有包子
}
代码-测试类
package com.qf.test.test12;
public class Test {
public static void main(String[] args) {
//实例化包子对象
BaoZi baoZi = new BaoZi();
//实例化 生产者线程
new MyThread01(baoZi).start();
//实例化消费者线程
new MyThread02(baoZi).start();
}
}



