标签:tst head 添加 bsp 调用 流程图 线程 stack code
昨天,由于工作比较繁忙,只是简单整理了一下java的线程的生命周期的流程图,今天就根据这个流程图来一步一步的讲解java多线程的知识。
图再来一遍:

也就是线程新建成功
public class MyThread extends Thread{
// 自己书写构造方法,两种方法都可
public MyThread(String name){
// super.setName(name);
super(name);
}
@Override
public void run() {
System.out.println("This is a Thread!");
}
}
// 一般方法
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
},"thread1");
// 函数式编程
Thread thread2 = new Thread(() ->System.out.println(Thread.currentThread().getName()),"thread2");
实际就是start方法,start方法是开启一个新的线程,如果只调用run方法,还是在主线程执行run方法,不会开启新的线程,线程不会进入到就绪状态,所以start方法才是开启线程的方法,
run方法中存入的只是任务内容。代码如下:
Thread thread = new Thread(() ->System.out.println(Thread.currentThread().getName()),"thead"); // 线程的启动 thread.start();
这一步的话,没有办法使用代码实现,因为呢,当线程执行start方法后,许多线程会去抢占cpu时间片,哪个线程抢占到了cpu时间片,哪个线程就进入到运行状态。
回到就绪态,就需要线程主动放弃抢到的cpu时间片,也就是大家常说的线程的礼让
但是需要注意的是,礼让不代表将cpu时间片彻底让给其他线程,还可能在次抢占时又获取到cpu时间片(没办法,有时候都不知道自己折磨厉害)
代码如下:
public static void main(String[] args) {
Runnable r = () -> {
for (int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " : " + i);
if(i == 3){
System.out.println(Thread.currentThread().getName() + " : " + i + "start use yield");
// 线程开始礼让
Thread.yield();
}
}
};
Thread t1 = new Thread(r,"thread1");
Thread t2 = new Thread(r,"thread2");
// 启动线程
t1.start();
t2.start();
}
故名思意就是阻塞了,线程暂停了,主要导致线程暂停的方法由:等待用户输入、使用sleep方法、使用jion方法
Thread thread = new Thread(() -> {
Scanner scanner = new Scanner(System.in);
int number = scanner.nextInt();
}, "thread1");
thread.start();
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0;i < 10;i++){
System.out.println(Thread.currentThread().getName()+" : "+i);
try {
// 没执行一次睡眠1s
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread1");
thread.start();
}
Thread类中的join方法的主要作用就是同步,使得线程之间的并行执行变为串行执行,切记join在start前面执行无效,不多说
public static void main(String[] args) {
// 创建两个线程
Thread thread1 = new Thread(() -> {
for(int i = 0;i < 10;i++){
System.out.println(Thread.currentThread().getName()+" : "+i);
}
},"thread1");
Thread thread2 = new Thread(() -> {
for(int i = 0;i < 10;i++){
System.out.println(Thread.currentThread().getName()+" : "+i);
}
},"thread2");
thread1.start();
// 使用线程同步方法
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
System.out.println("This is main Thread!");
}
执行多次后结果如下:
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread1 : 5
thread1 : 6
thread1 : 7
thread1 : 8
thread1 : 9
This is main Thread!
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
thread2 : 5
thread2 : 6
thread2 : 7
thread2 : 8
thread2 : 9
呦呵,thread1厉害了,比主线程优先执行完,还没有thread2与其抢占线程。
揪其原因如下: 程序在main线程中调用thread1线程的join方法,则main线程放弃cpu控制权,并返回thread线程继续执行直到线程t1执行完毕,
所以是thread1执行完后,主线程才执行,其实就是主线程中同步了thread1线程,执行join方法后,主线程阻塞,等thread1执行完必后,主线程继续执行
话不多说了,就是用户输入完必,sleep方法执行完毕、join方法执行完毕
首先,涉及到的内容为锁,那么什么条件可以用到锁呢,都有哪些锁呢
来,先看一个小问题,实现一个购票系统,4个购票员进行购票,代码如下:
// 定义售票箱的类
static class Ticket{
public static int number = 10;
}
// 定义四个售票员
// 使用四个线程进行模拟
public static void main(String[] args) {
Runnable r = () -> {
while(Ticket.number > 0){
System.out.println(Thread.currentThread().getName()+"start sell one ticket......"+"The remaining quantity of tickets is:"+ --Ticket.number);
}
};
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
来,查看部分结果:
thread - 1 start sell one ticket......The remaining quantity of tickets is:3
thread - 1 start sell one ticket......The remaining quantity of tickets is:2
thread - 1 start sell one ticket......The remaining quantity of tickets is:1
thread - 1 start sell one ticket......The remaining quantity of tickets is:0
thread - 4 start sell one ticket......The remaining quantity of tickets is:40
thread - 3 start sell one ticket......The remaining quantity of tickets is:41
??神魔鬼
原来都是资源共享惹的祸,这几个线程共享这个资源,造成了线程不安全
怎么整?
让他们排队用这个资源就好了呀,一个线程操作这个资源时,锁住资源,不让其他线程动即可,这也就有了锁
话不多说直接上代码:
// 定义售票箱的类
static class Ticket{
public static int number = 10;
}
// 定义四个售票员
// 使用四个线程进行模拟
public static void main(String[] args) {
Runnable r = () -> {
while(Ticket.number > 0){
// 对象锁 "" 任意写都行
// 类锁
// 此锁对于所有人需要都相同
synchronized (""){
if (Ticket.number <= 0){
return;
}
System.out.println(Thread.currentThread().getName()+"start sell one ticket...... "+"The remaining quantity of tickets is:"+ --Ticket.number);
}
}
};
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
话不多说直接上代码:
// 定义售票箱的类
static class Ticket{
public static int number = 10;
}
// 定义四个售票员
// 使用四个线程进行模拟
public static void main(String[] args) {
Runnable r = () -> {
while(SourceConflict.Ticket.number > 0){
sellTicket();
}
};
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
/**
* 同步方法如果为静态方法,锁位类锁,如果不是静态方法,则对应的是this
*/
public synchronized static void sellTicket(){
if(Ticket.number <= 0){
return;
}
System.out.println(Thread.currentThread().getName()+"start sell one ticket......"+"The remaining quantity of tickets is:"+ --SourceConflict.Ticket.number);
}
话不多说直接上代码:
// 定义售票箱的类
static class Ticket{
public static int number = 10;
}
// 定义四个售票员
// 使用四个线程进行模拟
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Runnable r = () -> {
while(Ticket.number > 0){
lock.lock();
if(Ticket.number <= 0){
return;
}
System.out.println(Thread.currentThread().getName()+"start sell one ticket......"+"The remaining quantity of tickets is:"+ --Ticket.number);
lock.unlock();
}
};
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
当某一代码段或者方法被锁住后,其他线程等待锁标记,无法访问就会进入锁池
提到锁,不得不说的就是死锁
来先来个代码,瞅一瞅:
public static void main(String[] args) {
Runnable runnable1 = () -> {
synchronized ("a"){
System.out.println("Thread1 gets lock named a");
synchronized ("b"){
System.out.println("Thread1 gets locks named a and b");
}
}
};
Runnable runnable2 = () -> {
synchronized ("b"){
System.out.println("Thread2 gets lock named b");
synchronized ("a"){
System.out.println("Thread2 gets lock named a and b");
}
}
};
Thread t1 = new Thread(runnable1);
Thread t2 = new Thread(runnable2);
t1.start();
t2.start();
}
这个就会锁到死,完全符合死锁的定义:死锁:多个线程彼此持有对方所需要的锁对象,而不释放自己的锁
runnable1占着a锁标记等b,rannable2占着b锁标记等a,等到死,也不释放,就产生了死锁
怎么解决呢,这时候就引出下一个内容,使用wait方法进入等待对列,之后通过唤醒进入锁池
为了解决上个死锁问题,我们采用让其中一个线程,拿到一个锁标记,执行完必后,释放掉锁标记,进入等待对列,等其他线程执行完必后,唤醒此线程即可。
代码如下:
public static void main(String[] args) {
Runnable runnable1 = () -> {
synchronized ("a"){
System.out.println("Thread1 gets lock named a");
try {
"a".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized ("b"){
System.out.println("Thread1 gets locks named a and b");
}
}
};
Runnable runnable2 = () -> {
synchronized ("b"){
System.out.println("Thread2 gets lock named b");
synchronized ("a"){
System.out.println("Thread2 gets lock named a and b");
"a".notifyAll();
}
}
};
Thread t1 = new Thread(runnable1);
Thread t2 = new Thread(runnable2);
t1.start();
t2.start();
}
notify:通知,是Object中的一个方法,唤醒等待队列中的一个线程,使这个线程进入锁池
notifyAll: 通知,是Object中得一个方法,唤醒等待队列中得所有线程,使这些线程全部进入锁池
锁池中的线程,拿到锁标记回到就绪态,也就是占有锁标记的线程将锁标记释放
标签:tst head 添加 bsp 调用 流程图 线程 stack code
原文地址:https://www.cnblogs.com/meililiuwei/p/13090415.html