java面向基础之多线程

流过昼夜 提交于 2020-02-27 03:34:59

学习多线程之前要先了解以下概念:

程序(program):是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
进程(process)程序的一次执行过程,或是正在运行的一个程序。动态过程:有它自身的产生、存在和消亡的过程 如:运行中的QQ
线程(thread),进程可进一步细化为线程,是一个程序内部的一条执行路径。
若一个程序可同一时间执行多个线程,就是支持多线程的
 
在javaApplication中,至少有一个main线程,但是后台(JVM)中还有一些其他的线程,GC、异常监视线程、类加载....
总结一下:
  • 线程是进程的其中一条执行路径,有的时候也成为轻量级的进程。
  • 线程是CPU调度的最小单位,进程是操作系统分配资源的最小单位。
  • 同一个进程的多个线程存在共享的内存,比如:堆、方法区是共享的,而栈(虚拟机栈,本地方法栈),程序计数器。

一、java要如何开启main意外的线程?

(1)继承Thread类
(2)实现Runnable接口
//继承Thread类
public class TestMyThread(){
public static void main(String[] args){
   MyThread my = new MyThread();
   my.start();
   for(int i=2;i<100;i+=2){
      System.out.println("偶数:"+i);
    }
   
  }
}


class MyThread extends Thread{
@Override
public void run(){
for(int i=2;i<100;i+=2){
    System.out.println("偶数:"+i);
    }
 }
}
//实现Runnable接口
public class TestMyRunnable(){
public static void main(String[] args){
   MyRunnable my = new MyRunnable ();
   Thread thread = new Thread(my);
   thread.start();



   for(int i=2;i<100;i+=2){
      System.out.println("偶数:"+i);
    }
   
  }
}


class MyRunnable implements Runnable{
@Override
public void run(){
for(int i=2;i<100;i+=2){
    System.out.println("偶数:"+i);
    }
 }
}

二、线程的生命周期

1.出生(新建)

当你new一个线程对象后,它就出生了,此时线程对象和普通的java对象没什么区别。

2.就绪

当线程启动(start)后,线程就会从出生状态到就绪状态。每个线程只能被start一次。

3.运行

正在被调度的状态,这个状态时间非常短暂,时间一到,线程回到就绪状态。

4.阻塞

5.死亡
 

 

Java线程优先级

Java线程优先级一共有10个等级:1-10;

Thread类中预定义了三个最基础的优先级:

  • MIN_PRIORITY:1
  • NORM_PRIORITY:5
  • MAX_PRIORITY:10

优先级高和低,影响了被调用的概率,但是不代表优先级低就完全没有机会。

控制线程

睡眠:sleep()

加塞:join()

暂停:tield()

线程的安全问题

两个线程使用了共享的同一份数据,就有线程的安全问题。

卖票:同时两个窗口卖票,可能会出现一张票被卖两次的情况。

1.如何判断?

(1)是否有多个线程使用同一个数据

(2)并且有多条语句来操作和访问这个共享数据

2.如何解决?加锁

同步:(1)同步的锁对象可以是任意类型的对象。

            (2)使用共享数据的这些线程,使用(承认)同一个锁对象

3.两种形式

(1)同步代码块

synchroized(同步的锁对象){
   XXXXXXX//需要锁起来的代码
}

(2)同步方法

如果你的一次任务是在一个方法中完成的,那么我可以直接锁一个方法。

【修饰符】synchronized 返回值类型  方法名(【形参列表】)【throws 异常列表】{}

线程通信

什么情况需要用到线程通信?
当遇到了“生产者-消费者”问题时,需要用到线程通信。线程通信就是用wait和notify方法来完成。

 

所谓的“生产者-消费者"问题是:
当一个(些)线程负责往"数据缓冲区"添加数据,
而另一个(些)线程只负责从"数据缓冲区"取数据。
当生产者慢了,那么会导致消费者半天没法从“数据缓冲区"取数据,
当消费者慢了,那么会导致"数据缓冲区”满了,我们的生产者就没法放了。

解决

(1)因为生产者与消费者要同时操作“数据缓冲区",那么“数据缓冲区”就是共享数据,这 时候就会有线程安全的。必须要同步

(2)因为“数据缓冲区”的大小是有限的,那么就需要通信,就要用wait和notify/notifyA11方法wait和notify方法必须用“同步锁”对象调用。

当如果用“非同步锁”对象调用时,一定会报11legalMonitorstateException, "同步锁”对象又称为“监视器”对象。

wait和notify方法在Object类中声明,为啥呢?

因为我们要用“同步锁”对象,而“同步锁”对象可以是任意类型

死锁

一个对话形象描述死锁:

面试官:给我解释一下死锁。

我:你先给我offer,我就给你解释。

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!