Java多线程相关知识

多线程:
1.基础
进程:指正在运行的程序
线程:线程是进程中的一个执行单元。比进程小,一个进程包含多个线程
总之:一个程序运行,至少有一个进程,一个进程包含多个线程。
多线程:一个程序中有多个线程同时运行
2.程序运行原理
分时调度
抢占式调度
Java中实现现成的三种方式:
继承Thread类创建线程类。
通过Runnable接口类创建线程类。
通过Callable和Future创建线程。
1.继承Thread类
简介:
线程是程序中执行的线程。 Java虚拟机允许应用程序同时执行多个执行线程。
每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守护程序。 当在一些线程中运行的代码创建一个新的 Thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护线程。

当Java虚拟机启动时,通常有一个非守护进程线程(通常调用某个指定类的名称为 main的方法)。 Java虚拟机将继续执行线程,直到发生以下任一情况:

该 exit类的方法 Runtime已经被调用并且安全管理器允许退出操作发生。
不是守护进程线程的所有线程都已经死亡,无论是从调用返回到 run方法还是抛出异常,传播超出了 run方法。
创建一个新的执行线程有两种方法。 一个是将一个类声明为一个 Thread的子类。 这个子类应该重写 run类的方法 Thread 。 然后可以分配并启动子类的实例。

常用方法:

方法名 描述
currentThread() 返回对当前正在执行的线程对象的引用。
interrupt() 中断这个线程。
isAlive() 测试这个线程是否活着。
join() 等待这个线程死亡。
run() 如果这个线程是使用单独的Runnable运行对象构造的,那么这个Runnable对象的run方法被调用; 否则,此方法不执行任何操作并返回。
sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数,这取决于系统定时器和调度程序的精度和准确性。
start() 导致此线程开始执行; Java虚拟机调用此线程的run方法。
yield() 对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。 3.应用
package 线程1;

public class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name+“运行”+(i+1)+“次”);
}
}
public static void main(String[] args) {
MyThread t1=new MyThread(“线程1”);
MyThread t2=new MyThread(“线程2”);
t1.start();
t2.start();
}
}

实现Runnable接口:
package 线程1;

public class MyThread02 implements Runnable{
private String name;
public MyThread02(String name){
this.name=name;
}
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println(name+“运行”+(i+1)+“次”);
}
}
public static void main(String[] args) {
MyThread02 mt1=new MyThread02(“线程A”);
MyThread02 mt2=new MyThread02(“线程B”);
Thread t1=new Thread(mt1);
Thread t2=new Thread(mt2);
t1.start();
t2.start();
}
//线程的启动用start(),多个线程时无法确定谁先执行
}

实现Callable接口:
继承Thread类与实现Runnable接口的不同:
1)Runnable提供run方法,不会抛出异常,只能在run方法内部处理异常。Callable提供call方法,直接抛出Exception异常,也就是你不会因为call方法内部出现检查型异常而不知所措,完全可以抛出即可。
2)Runnable的run方法无返回值,Callable的call方法提供返回值用来表示任务运行的结果
3)Runnable可以作为Thread构造器的参数,通过开启新的线程来执行,也可以通过线程池来执行。而Callable只能通过线程池执行。
4)继承Thread类,不适合多个线程共享资源,实现Runnable可以进行资源共享。
package 线程1;
//继承Thread类
public class MyThread03 extends Thread{
private int ticket=10;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if(this.ticket>0){
System.out.println(“买票:ticket”+(ticket–));
}
}
}

public static void main(String[] args) {
    MyThread03 mt1=new MyThread03();
    MyThread03 mt2=new MyThread03();
    MyThread03 mt3=new MyThread03();
    mt1.start();
    mt2.start();
    mt3.start();
}

}
运行结果三个点各卖十张票
package 线程1;
//runnable接口三个点共卖十张票
public class MyThread04 extends Thread{
private int ticket=10;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if(this.ticket>0){
System.out.println(“买票:ticket”+(ticket–));
}
}
}
public static void main(String[] args) {
MyThread04 mt=new MyThread04();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
}
}
1.适合多个线程共享同一资源
2.避免了Java单继承带来的局限
3.程序具有健壮性,因为可以共享资源,代码与数据相互独立。
线程的方法的应用:
currentThread()方法:
package 线程1;

public class MyThread04 extends Thread{

@Override
public void run() {
    for (int i = 0; i < 3; i++) {
        System.out.println(Thread.currentThread().getName()+"运行"+(i+1));
    }
}

public static void main(String[] args) {
    System.out.println(5/0);
    MyThread04 mt=new MyThread04();
    new Thread(mt).start();
    new Thread(mt,"线程A").start();
    new Thread(mt,"线程B").start();
    new Thread(mt).start();
}

}
isAlive()
package 线程1;

public class MyThread04 extends Thread{

@Override
public void run() {
    for (int i = 0; i < 3; i++) {
        System.out.println(Thread.currentThread().getName()+"运行"+(i+1));
    }
}

public static void main(String[] args) {
    MyThread04 mt=new MyThread04();
    Thread t1=new Thread(mt,"线程AA");
    System.out.println("线程开始之前:"+t1.isAlive());
    t1.start();
    System.out.println("线程开始之后:"+t1.isAlive());
}

}

sleep()
package 线程1;

public class MyThread04 extends Thread{

@Override
public void run() {
    for (int i = 0; i < 30; i++) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行"+i);
    }
}

public static void main(String[] args) {
    MyThread04 mt=new MyThread04();
    Thread t1=new Thread(mt,"线程AA");
    t1.start();
}

}

面试题:线程方法调用时为什么只能用thy/catch,而不能用throws
join()
package 线程1;

public class MyThread04 extends Thread{

@Override
public void run() {
    for (int i = 0; i < 30; i++) {
        System.out.println(Thread.currentThread().getName()+"运行"+i);
    }
}

public static void main(String[] args) throws InterruptedException {
    MyThread04 mt=new MyThread04();
    Thread t1=new Thread(mt,"线程AA");
    Thread t2=new Thread(mt,"线程BB");
    t1.start();
    t1.join(100);
    t2.start();
}

}

优先级:
Java多线程中有优先级。优先级的范围在1~10.值越大优先级就越高。
默认值为5,如果设置了线程的优先级,不能保证该线程一定先执行,只能提高该线程优先执行的可能性。
package 线程1;

public class MyThread04 extends Thread{

@Override
public void run() {
    for (int i = 0; i < 30; i++) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行"+i);
    }
}

public static void main(String[] args) {
    MyThread04 mt=new MyThread04();
    Thread t1=new Thread(mt,"线程AA");
    Thread t2=new Thread(mt,"线程BB");
    Thread t3=new Thread(mt,"线程CC");
    t1.setPriority(Thread.MAX_PRIORITY);
    t2.setPriority(Thread.MIN_PRIORITY);
    t1.start();
    t2.start();
    t3.start();
}

}

生命周期:
当线程被创建并启动后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New)、就绪(Ready)、运行(Running)、阻塞(Blocked)、和死亡(Dead)5种状

(1)新建状态
创建线程对象后就处于新建状态
new 关键字
(2)就绪状态
调用start方法启动线程时,就进入就绪状态。
(3)运行状态
调用run()方法时就处于运行状态
(4)阻塞状态
正常的线程对象受到外力的干预,暂时终止运行
(5)死亡状态
线程执行完毕,或者调用stop()方法

同步与死锁:
package 线程1;

public class MyThread03 extends Thread{
private int ticket=10;

@Override
public void run() {
    for (int i = 0; i < 20; i++) {
        if(this.ticket>0){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("买票:ticket="+(ticket--));
        }
    }
}

public static void main(String[] args) {
    MyThread03 mt1=new MyThread03();
    Thread t1=new Thread(mt1);
    Thread t2=new Thread(mt1);
    Thread t3=new Thread(mt1);
    t1.start();
    t2.start();
    t3.start();
}

}

运行结果出现两个问题:
1.票数为负。
2.重复买票
为了解决资源共享,所出现的以上问题,可以用同步解决(同步代码块,同步方法)
同步格式:
synchronized(同步对象) {
          代码块
}
同步代码块:
package 线程1;

public class MyThread03 extends Thread{
private int ticket=10;

@Override
public void run() {
    for (int i = 0; i < 20; i++) {
        synchronized (this){
            if(this.ticket>0){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("买票:ticket="+(ticket--));
            }
        }
    }
}

public static void main(String[] args) {
    MyThread03 mt1=new MyThread03();
    Thread t1=new Thread(mt1);
    Thread t2=new Thread(mt1);
    Thread t3=new Thread(mt1);
    t1.start();
    t2.start();
    t3.start();
}

}

同步方法:

package 线程1;

public class MyThread03 extends Thread{
private int ticket=10;

@Override
public void run() {
    for (int i = 0; i < 20; i++) {
        this.sale();
    }
}
public synchronized void sale(){
    if(this.ticket>0){
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("买票:ticket="+(ticket--));
    }
}

public static void main(String[] args) {
    MyThread03 mt1=new MyThread03();
    Thread t1=new Thread(mt1);
    Thread t2=new Thread(mt1);
    Thread t3=new Thread(mt1);
    t1.start();
    t2.start();
    t3.start();
}

}

死锁
使用同步可以保证程序的正确执行,过多的同步会造成死锁。
死锁:之两个线程等待彼此先完成,造成了程序的停滞。死锁都是在运行时才产生的。

生产者消费者案例

(以上内容均为自己理解,有不对的地方,请大家积极指正,谢谢大家的阅读)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧瑟授衣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值