java_线程

12 篇文章 0 订阅
3 篇文章 0 订阅
启动线程的第一种方法
package com.bjpowernode.java.thread;
/*
 实现线程的第一种方法:
 编写一个类,直接继承java.lang.Thread,重写run方法

 怎么创建线程对象??
 怎么启动线程??
 */
public class ThreadTest02 {
    public static void main(String[] args) {
        // 这里是main方法,这里属于主线程,在主栈中运行
        // 新建一个分支线程对象
        MyThread myThread=new MyThread();
        // 启动线程
        myThread.start(); // start方法的作用:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码的任务完成之后,瞬间就结束了
        // 这段代码只是为了开辟一个新的栈空间,只要新的栈空间开辟出来,次方法就结束了,线程就启动了
        // 启动成功的线程就会自动调用run方法,并且run方法在分支栈的栈底部
        // run在分支栈的栈底部,main在主栈的栈底部
        // 这里的代码还是在主线程中
        for (int i=0;i<1000;i++){
            System.out.println("主线程---->"+i);
        }

    }
}
class MyThread extends Thread {
    @Override
    public void run() {
        // 编写程序,这段程序运行在分支栈中
        for (int i=0;i<1000;i++){
            System.out.println("分支线程启动--->"+i);

        }
    }
}


启动线程的第二种方式
package com.bjpowernode.java.thread;
/*
 启动线程的第二种方式:编写一个类,实现java.lang.Runnable接口

 */
public class ThreadTest03 {
    public static void main(String[] args) {
        // 创建一个可运行的对象
        MyRunnable myRunnable=new MyRunnable();
        // 将可运行的对象封装成一个线程对象
        Thread thread=new Thread(myRunnable);
        // 启动线程
        thread.start();
        for (int i=0;i<1000;i++){
            System.out.println("主线程---->"+i);
        }

    }
}
// 这并不是一个线程,是一个可运行的类,它还不是一个线程
class MyRunnable implements Runnable {

    @Override
    public void run() {
        for (int i=0;i<1000;i++){
            System.out.println("分支线程---->"+i);
        }
    }
}


采用匿名内部类去启动线程(使用接口去启动线程)
package com.bjpowernode.java.thread;
/* 
 启用匿名内部类来
 */
public class ThreadTest04 {
    public static void main(String[] args) {
        // 创建一个线程兑现
        Thread t=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<100;i++){
                    System.out.println("分支线程的启动"+i);
                }
            }
        });
        // 启动线程
        t.start();
        for (int i=0;i<100;i++){
            System.out.println("主线程启动"+i);
        }
    }
}

获取当前线程
package com.bjpowernode.java.thread;
/*
1.怎么获取线程对象??
 static Thread	currentThread()
 返回对当前正在执行的线程对象的引用。
2,获取线程对象的名字
3,修改线程对象的名字
4.当线程没有修改名字时,线程有自己默认的名字 Thread-0  Thread-1
 */
public class ThreadTest05 {
    public static void main(String[] args) {
        // 获取当前线程
        // 这个方法出现在main方法当中,所以当前线程就是主线程
        Thread currentThread =Thread.currentThread();
        System.out.println(currentThread.getName()); // main
        // 创建线程的对象
        MyThread2 myThread2=new MyThread2();
        // 设置线程的名字
        myThread2.setName("ttt");
        // 获取线程的名字
        String s=myThread2.getName();
        System.out.println(s);
        // 启动线程
        myThread2.start();
    }
}
class MyThread2 extends Thread {
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            System.out.println("分支线程"+i);
        }
    }
}


让当前线程处于阻塞状态(sleep方法)
package com.bjpowernode.java.thread;
/*
关于线程的sleep方法:阻塞状态
static void	sleep(long millis)
1.静态方法:Thread.sleep(1000)
2.参数是毫秒
3.作用:让当前对象进入休眠,进入“阻塞状态” 放弃占用的CPU时间片,让给其他线程使用
   出现在哪,就让当前线程睡觉
   
   4.Thread代码可以让他们在特定的时间执行特定在代码
 */
public class ThreadTest06 {
    public static void main(String[] args) {
        // 让当前线程进入休眠,睡眠5秒
//        try {
//            Thread.sleep(5*1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        // 5秒后执行这里的代码
        // System.out.println("hello world");

        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+"---->"+i);
            // 睡眠一秒
            try {
                Thread.sleep(5*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

阻塞面试题
package com.bjpowernode.java.thread;
/*
关于Thread.sleep()的面试题
 */
public class ThreadTest07 {
    public static void main(String[] args) {
        // 创建线程对象
        Thread t=new MyThread3();
        // 修改线程名字
        t.setName("tt");
        // 获取线程名字
        System.out.println(t.getName());
        // 启动线程
        t.start();
        // 调用sleep方法
        try{
            // 问题:这行代码会让线程进入休息状态吗??
            // 当前线程为main方法,main线程会进入休眠状态
            Thread.sleep(5*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello world");
    }
}
class MyThread3 extends Thread {
    public void run(){
        for (int i=0;i<1000;i++){
            System.out.println(Thread.currentThread().getName()+"----->"+i);
        }
    }

}

怎么叫醒一个正在睡眠的线程
package com.bjpowernode.java.thread;
/*
怎么叫醒一个正在休眠的线程
 */
public class ThreadTest08 {
    public static void main(String[] args) {
        // 创建线程对象
        Thread t=new Thread(new MyRunnable2());
        t.setName("t");
        t.start();
        // 希望中断睡眠 醒来
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 中断t线程的睡眠
        t.interrupt();// 干扰 靠异常处理机制去处理

    }
}
class MyRunnable2 implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"---->begin");
        try {
            // 睡眠一年
            Thread.sleep(1000*60*60*24*365);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"---->end");
    }

}

如何强行终止一个线程
package com.bjpowernode.java.thread;
/*
如何强行终止一个线程
这种方式不建议使用,容易丢失数据
 */
public class ThreadTest09 {
    public static void main(String[] args) {
        Thread t=new Thread(new MyRunnable3());
        t.setName("t");
        t.start();
        // 模拟5秒
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 5秒后强行终止t线程
        t.stop();// 不建议使用

    }
}
class MyRunnable3 implements Runnable {

    @Override
    public void run() {
        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+"---->"+i);
            try {
                Thread.sleep(1000*1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
合理终止一个线程
package com.bjpowernode.java.thread;
/*
合理终止一个线程
 */
public class ThreadTest10 {
    public static void main(String[] args) {
        MyRunnable4 r=new MyRunnable4();
        Thread t=new Thread(r);
        t.setName("t");
        t.start();
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 终止线程
        r.flag=false;


    }
}
class MyRunnable4 implements Runnable {

    boolean flag=true;
    @Override
    public void run() {
        for (int i=0;i<10;i++){
            if (flag){
                System.out.println(Thread.currentThread().getName()+"---->"+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            else {
                // 终止线程
                return;
            }
        }
    }
}

线程排队执行
package com.bjpowernode.java.threadsafe2;
/*
银行账户
使用线程同步机制,解决线程安全问题
 */
public class Account {
    // 账号
    private String actno;
    // 余额
    private double balance;

    public Account(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }

    public Account() {
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    // 取款的方法
    public void withdraw(double money){
      // 以下这几行代码必须是线程排队,不能并发
        // 一个线程把这里的代码全部执行结束后,另一个线程才开始进来
        /*
        线程同步机制的语法:
        synchronized(){
        // 线程同步代码块
        }
        synchronized() 里面传的数据是非常重要的,
        这个数据必须要是多线程共享的数据,才能大袋多线程排队

        () 里面写什么??
        那要看你想让那些线程同步
        假设t1,t2,t3,t4,t5,有5个线程
        你只希望t1,t2,t3排队,t4,t5不排队,怎么办?
        你一定要在()中写一个t1,t2,t3共享的对象,而这个
        对象t4,t5来说不是共享的

        这里的共享对象是:账户对象
        账户对象是共享的,那么this就是代表的当前对象
         */
        synchronized (this){
            double before=this.getBalance();
            double after=before-money;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setBalance(after);
        }
    }

}



package com.bjpowernode.java.threadsafe2;

public class AccountThread extends Thread {
    // 两个线程必须共享同一个账户
    private Account act;
    // 通过构造方法传递过来的账户对象

    public AccountThread(Account act) {
        this.act = act;
    }

    @Override
    public void run() {
        // run方法的执行表示取款操作
        // 假设取款5000
        double money=5000;
        // 取款
        act.withdraw(money);
        System.out.println("账户"+act.getActno()+"取款成功,余额"+act.getBalance());

    }
}






package com.bjpowernode.java.threadsafe2;

public class Test {
    public static void main(String[] args) {
        // 创建账户对象
        Account act=new Account("act-001",10000);
        // 创建两个线程
        Thread t1=new AccountThread(act);
        Thread t2=new AccountThread(act);
        // 设置name
        t1.setName("t1");
        t2.setName("t2");
        // 启动线程
        t1.start();
        t2.start();
    }
}

死锁(必须会)
package com.bjpowernode.java.deadlock;
/*
死锁:
死锁代码要会写
只有会写的,才会在以后开发中注意这个问题
因为死锁很难调试
 */
public class DeadLock {
    public static void main(String[] args) {
        Object o1=new Object();
        Object o2=new Object();
        // t1和t2线程共享o1和o2
        Thread t1=new MyThread1(o1,o2);
        Thread t2=new MyThread2(o1,o2);
        t1.start();
        t2.start();


    }
}
class MyThread1 extends Thread {
    Object o1;
    Object o2;

    public MyThread1(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }
    public void run(){
        synchronized (o1){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){

            }
        }

    }
}
class  MyThread2 extends Thread {
    Object o1;
    Object o2;

    public MyThread2(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }
    public void run(){
        synchronized (o2){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){

            }
        }

    }

}

守护线程
package com.bjpowernode.java.thread;
/*
守护线程
 */
public class ThreadTest14 {
    public static void main(String[] args) {
        Thread t=new BakDataThread();
        t.setName("t");
        // 启动线程之前将t设置为守护线程
        t.setDaemon(true); // 只要主线程完成用户线程一定会结束
        t.start();

        // 主线程是用户线程
        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+"--->"+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
class BakDataThread extends Thread {
    public void run(){
        int i=0;
        while(true){
            System.out.println(Thread.currentThread().getName()+"----->"+(++i));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

定时器(以后在SpringTask中可以用)
  • SpringTask中也是基java.util.Timer下去编写的
package com.bjpowernode.java.thread;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

/*
定时器去定时任务
 */
public class TimeTest {
    public static void main(String[] args) throws Exception {
        // 创建定时器对象
        Timer timer=new Timer();

        // 指定定时任务
        // 获取时间
        // timer.schedule(定时任务,第一次执行时间,间隔多久执行一次);

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date firstTime=sdf.parse("2022-04-05 17:14:30");
        timer.schedule(new LogTimerTask(),firstTime,1000*10);
    }
}
// 编写一个定时任务
//假设这是一个记录日志的定时任务  TimeTask是一个抽象类
class LogTimerTask extends TimerTask {

    @Override
    public void run() {
        // 编写你需要执行的定时任务
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strTime=sdf.format(new Date());
        System.out.println(strTime+"完成了一次数据备份");
    }
}

实现线程的第三种方式(Callable接口)
package com.bjpowernode.java.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;// 属于java的并发包

/*
实现线程的第三种方式
 实现Callable接口
 */
public class ThreadTest15 {
    public static void main(String[] args) {
        //第一步:创建一个“未来任务类”对象
        FutureTask task=new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception { //call()方法相当于run()方法,只不过这个有个返回值
                // 线程执行一个任务,执行之后可能会有一个执行结果
                // 模拟执行
                System.out.println("call begin");
                Thread.sleep(1000*10);
                System.out.println("call end");
                int a=100;
                int b=200;

                return a+b;// 自动装箱(Integer)
            }
        });

        // 创建一个线程对象
        Thread t=new Thread(task);

        // 启动线程
        t.start();
        // 在这里是main方法,这是主线程
        // 怎么获取t线程的返回值

        try {
            // 直接get()
            // 这里会导致当前线程阻塞
            Object obj=task.get();
            System.out.println("线程执行结果:"+obj);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // main方法这里的程序要想执行必须等待get()方法结束
        // 而get()方法可能需要很久,因为get()要拿另一个线程的返回值
        // 另一个线程是需要时间的
        System.out.println("hello");
    }
}

生产和消费平衡
  • 注意理解
package com.bjpowernode.java.thread;

import java.util.ArrayList;
import java.util.List;

/*
1.生产和消费者模式
  供求平衡
  wait();和notify();方法不是线程对象的方法
  这两个方法需要建立在线程同步的基础上的

  o.wait()让正在o对象的线程进入等待状态,并且释放o对象对应的锁
  o.notify();让o对象上的线程唤醒,不会释放o对象上占有的锁

  模拟这样一个需求:
  创库我们采用List集合,
  List集合中只能存储一个元素
  1个元素就表示创库满了
  如果是0,那么表示创库空了
  做到供求平衡
 */
public class ThreadTest16 {
    public static void main(String[] args) {
        // 创建一个创库对象,两个线程共享
        List list=new ArrayList();
        // 创建两个线程对象
        // 生产者线程
        Thread t1=new Thread(new Producer(list));
        // 消费者线程
        Thread t2=new Thread(new Consumer(list));

        t1.setName("生产者线程");
        t2.setName("消费者线程");

        t1.start();
        t2.start();


    }
}
// 生产线程
class Producer implements Runnable {
    // 创库
    private List list;

    public Producer(List list) {
        this.list = list;
    }

    public Producer() {
    }

    @Override
    public void run() {
        // 一直生产
        // 使用死循环来一直生产
        while (true){
            // 给创库List 加锁
            synchronized (list){
                if(list.size()>0){
                    // 当前线程进入等待状态
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                // 程序可以执行到这里,说明创库是空的,我需要生产线程
                Object obj=new Object();
                list.add(obj);
                System.out.println(Thread.currentThread().getName()+"----->"+obj);
                // 唤醒消费者消费
                list.notify();
            }
        }
    }
}
// 消费线程
class Consumer implements Runnable {
    // 创库
    private List list;

    public Consumer(List list) {
        this.list = list;
    }

    public Consumer() {
    }

    @Override
    public void run() {
        // 一直消费
        while (true){
            synchronized (list){
                if (list.size()==0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 程序能够执行到此处,说明创库中有线程,需要消费
                Object obj=list.remove(0);
                System.out.println(Thread.currentThread().getName()+"---->"+obj);
                // 唤醒生产者生产
                list.notify();

            }
        }

    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值