Java 多线程篇(1)

7 篇文章 0 订阅
6 篇文章 0 订阅

Java 多线程篇(1)

在java开发过程中通常会遇到需要多条路径来执行某个任务,比如一个后台程序连接多个客户端,不可能让一个客户端完成它所有的工作之后才能让其他客户端连接
因此就需要使用的多线程技术

一个java程序至少包含俩个线程,1.主线程 2. 垃圾回收线程
本身的函数是一条主线程

多线程是为了同时运行多部分的代码,但CPU只有一个,因此是在多个线程中随机切换,所以一旦线程过多会影响效率

java中使用多线程的两种方式
一、通过继承Thread类

首先通过继承Thread类并重写Thread中的run方法,run方法中的内容是线程的执行任务

Thread 类中有start()方法,用来开启线程执行run方法中的内容
stop()方法则是终止线程的执行

public class MyDemo extends Thread {

    public void run() {
        for (int i = 0; i < 50; i++)
            System.out.println("---" + i);
    }

    public static void main(String[] args) {
        MyDemo mydemo = new MyDemo();
        MyDemo mydemo2 = new MyDemo();
        mydemo.start();
        mydemo2.start();
    }
}


运行结果:
—0 —0 —1 —2 —3 —4 —1 —5 —2 —6 —7 —8 —9 —10 —11 —12
—13 —14 —15 —16 —17 —18 —19 —20 —21

两个线程将会执行run 方法中的代码
并且两个线程的运行是随机的,cpu在两个线程之间随机切换

二、实现Runnable接口
class Demo  implements Runnable{
    public void run(){
        show();
    }

    Demo  d = new Demo();//先创建继承了接口的类的对象,
    Thread t1 = new Thread (d);//需要将对象传入线程中
    Thread t2 = new Thread (d);
    t1.start();
    t2.start();
}

Runnable中只有一个方法就是run() <仅仅是为了将线程任务进行对象的封装>

原理:
class Thread implements Runnable{
    private Runnable r;
    Thread(){}
    Thread(Runnable r){
        this.r = r;
    }
    public void run(){
        if(r!=null){
            r.run();
            }
    }
    public void start(){
        run();
    }
}

Thread 类中有多个构造方法,其中有一个需要传入对象 还有一个不需要任何参数
所以如果有对象传入将会把该对象中的run()方法也传入,从而利用线程对象调用的start()方法能完成 传入的对象 的任务(run方法)

使用接口的好处:
  • 将线程的任务从子类中分离进行了单独封装
  • 避免单继承的局限性

    利用实现Runnable接口完成多线程更常用

线程有几个常用的方法
 - void run();线程的主要执行代码

 - void start();使该线程开始启动,Java 虚拟机负责调用该线程的 run()方法。
                //多次启动一个线程是非法的。

 - void stop();中断线程的运行

 - void sleep(long millis):Thread类静态方法,线程进入阻塞状态,在指定时间(单位为毫秒)到达之后进入
                       //就绪状态,而非立即进入执行状态。

 - void wait();使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块

 - void notify();唤醒在此对象监视器上等待的单个线程,如果等待线程有多个,则会选择唤醒其中一个线程
                  进入就绪状态,选择是任意性的

 - void notifyAll()   唤醒此对象上的所有等待的线程使他们进入就绪状态

 - void  yield():静态方法,当前线程放弃占用CPU资源,回到就绪状态,使其他优先级不低于此线程
                  的线程有机会被执行。 

 - void setPriority(int newPriority):设置当前线程的优先级。

 - int getPriority():获得当前线程的优先级。

 -void join();调用线程被阻塞,知道join方法加入的线程执行完成时候再继续执行 

wait notify() notifyAll() 这三个方法都是属于Object类的方法,只能在同步控制方法或者同步控制块里面使用

sleep()和wait()的区别

  • 首先一个最明显的区别是 wait是Object类的方法,而sleep()是Thread类的静态方法,谁调用了该方法谁去休眠
  • 比较重要的一点是sleep没有释放出锁,而wait释放了锁,一般wait不会加时间限制,需要用notify来唤醒
  • wait只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
  • sleep()使用时需要捕获异常 利用
    try { Thread.sleep(100);//睡眠100毫秒 }
    catch(InterruptedException e) { }
join()方法
//假设此线程为1线程
package yd;

public class Main extends Thread {

    /**
     * 主函数
     */
    public static void main(String[] args) {
        new Main().start();
    }

    public void run() {
        JoinThread jt = new JoinThread();
        jt.start();
        try {
            jt.join();// join线程加入,主线程阻塞
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("main线程执行");
    }
}

class JoinThread extends Thread {

    public void run() {
        System.out.println("join线程执行");
        try {
            sleep(1000);//加上睡眠,便于观察
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

运行结果:
join线程执行 (过了一秒之后)(这一秒是sleep中的设置的)
mian线程执行

守护线程 Daemon
代码实例
public class Main {

    /**
     * 主函数
     */
    public static void main(String[] args) {
        JoinThread jt = new JoinThread();
        jt.start();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        jt.flag = false;

    }
}

class JoinThread extends Thread {
    static boolean flag = true;

    public void run() {
        int num = 0;
        DaemonThread dt = new DaemonThread();
        dt.setName("守护线程---");
        dt.setDaemon(true);
        dt.start();
        while (flag) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + num++);
        }
        System.out.println(Thread.currentThread().getName() + "结束");
    }
}

class DaemonThread extends Thread {

    public void run() {
        int num = 0;
        while (true) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + num++);
        }
    }
}
结果:
守护线程---0  Thread-00
守护线程---1  Thread-01
守护线程---2  Thread-02
守护线程---3  Thread-03
守护线程---4  Thread-04
守护线程---5  Thread-05
守护线程---6  Thread-06
Thread-07  守护线程---7
守护线程---8 Thread-08 
Thread-09  守护线程---9(守护线程随着Thread的结束而结束)

如果将dt.setDaemon(true);注释掉之后
当Thread运行到9 的时候结束
但是 dt线程会继续运行

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值