600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 对Java多线程编程的初步了解 实现多线程的三种方式以及多线程并发安全的线程同步机制

对Java多线程编程的初步了解 实现多线程的三种方式以及多线程并发安全的线程同步机制

时间:2022-03-30 22:10:06

相关推荐

对Java多线程编程的初步了解 实现多线程的三种方式以及多线程并发安全的线程同步机制

什么叫进程?什么叫线程?

进程相当于一个应用程序,线程就是进程中的一个应用场景或者说是一个执行单元,一个进程可以启动多个线程,每个线程执行不同的任务,一个线程不能单独存在,他必须是进程的一部分,当进程中所有的非守护线程都结束运行后,这个进程也随之结束。对于Java程序来说,JVM就是一个进程,JVM会启动一个主线程调用main方法,还会启动一个垃圾回收线程负责看护,回收垃圾。所以,java程序中至少有两个线程并发。(注意:进程和进程之间内存独立不共享,但线程与线程之间存在资源共享,在java中,线程和线程之间共享堆内存和方法区内存,但栈内存独立,一个线程会开辟一个栈空间,互不干扰,所以说,main方法结束后,java程序也可能没结束,因为main方法结束只意味着主线程结束了,但其他线程可能还在运行,即主栈空了,其它栈还在进行压栈弹栈)

对于单核CPU真的能做到真正的多线程并发吗?

首先对于多核CPU来说,真正的多线程并发是没有问题的。例如,8核CPU就可以在同一时间点,做到真正的有8个线程并发执行。但单核CPU并不能做到真正的并发执行,只不过在线程与线程之间来回切换十分迅速,给人一种在并发执行的错觉。

java中实现多线程的三种方式?

1.编写一个类,直接继承java.lang.Thread,重写run方法。

/*实现线程的第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法。怎么创建线程对象? new就行了。怎么启动线程呢? 调用线程对象的start()方法。注意:亘古不变的道理:方法体当中的代码永远都是自上而下的顺序依次逐行执行的。* */public class ThreadTest02 {public static void main(String[] args) {MyThread mt = new MyThread();mt.start();//这个方法会新开一个栈空间,启动一个分支线程,完成这个任务,这个方法就结束了,这个方法结束后,线程进入到就绪状态// 启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)。for (int i = 0; i < 1000; i++) {System.out.println("主线程执行当中:" + i);}}}class MyThread extends Thread {public void run() {//这个方法里的程序运行在分支线程中,在新开的栈空间的栈底,这个方法结束了,也就意味着这个线程结束了for (int i = 0; i < 1000; i++) {System.out.println("分支线程执行当中:" + i);}}}

2.编写一个类,实现java.lang.Runnable接口,实现run方法。

public class ThreadTest03 {public static void main(String[] args) {Thread t = new Thread(new MyRunnable());t.start();for (int i = 0; i < 1000; i++) {System.out.println("主线程执行当中:" + i);}}}class MyRunnable implements Runnable {public void run() {for (int i = 0; i < 1000; i++) {System.out.println("分支线程执行当中:" + i);}}}

3.实现Callable接口,这种方式可以获取线程的返回值(jdk8新特性)

import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;/*守护线程的第三种方式:实现Callable接口这种方式的优点:可以获取到线程的执行结果。这种方式的缺点:效率比较低,在获取t线程执行结果的时候,当前线程受阻塞,效率较低。* */public class ThreadTest12 {public static void main(String[] args) throws ExecutionException, InterruptedException {// 第一步:创建一个“未来任务类”对象。// 参数非常重要,需要给一个Callable接口实现类对象。FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {// call()方法就相当于run方法。只不过这个有返回值Thread.sleep(1000 * 5);return 10 + 10;}});Thread t = new Thread(task);t.start();Integer it = task.get();//在主线程中获取t线程的结果,在拿到t线程的结果之前,主线程会卡在这里System.out.println("t线程的结果为:" + it);System.out.println("bye bye");}}

线程的生命周期

关于线程的调度

1、常见的线程调度模型有哪些?

抢占式调度模型:那个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些。java采用的就是抢占式调度模型。均分式调度模型:平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样。平均分配,一切平等。有一些编程语言,线程调度模型采用的是这种方式。

2、java中提供了哪些方法是和线程调度有关系的呢?

实例方法:void setPriority(int newPriority) 设置线程的优先级int getPriority() 获取线程优先级最低优先级1默认优先级是5最高优先级10优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)静态方法:static void yield() 让位方法暂停当前正在执行的线程对象,并执行其他线程yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用。yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。注意:在回到就绪之后,有可能还会再次抢到。实例方法:void join() 合并线程class MyThread1 extends Thread {public void doSome(){MyThread2 t = new MyThread2();t.join(); // 当前线程进入阻塞,t线程执行,直到t线程结束。当前线程才可以继续。}}class MyThread2 extends Thread{}

关于多线程并发环境下,数据的安全问题。

1.什么时候数据在多线程并发的环境下会存在安全问题呢?

当多线程并发的环境下,有共享数据,并且这个数据还会被修改,此时就存在线程安全问题。

2、怎么解决线程安全问题呢?

使用“线程同步机制”,synchronized。线程同步就是线程排队了,线程排队了就会牺牲一部分效率。

3、关于线程这块的两个编程模型:

异步编程模型:线程t1和线程t2,各自执行各自的,t1不管t2,t2不管t1,谁也不需要等谁,这种编程模型叫做:异步编程模型。其实就是:多线程并发(效率较高。)异步就是并发。同步编程模型:线程t1和线程t2,在线程t1执行的时候,必须等待t2线程执行结束,或者说在t2线程执行的时候,必须等待t1线程执行结束,两个线程之间发生了等待关系,这就是同步编程模型。效率较低。线程排队执行。同步就是排队。

Java中三大变量在多线程并发中的安全问题

实例变量:在堆中。

静态变量:在方法区。

局部变量:在栈中。

以上三大变量中:

局部变量永远都不会存在线程安全问题。

因为局部变量不共享。(一个线程一个栈。)

局部变量在栈中。所以局部变量永远都不会共享。

实例变量在堆中,堆只有1个。

静态变量在方法区中,方法区只有1个。

堆和方法区都是多线程共享的,所以可能存在线程安全问题。

局部变量+常量:不会有线程安全问题。

成员变量:可能会有线程安全问题。

线程同步机制,synchronized的三种用法

第一种:同步代码块

synchronized(线程共享对象){

同步代码块; }

第二种:在实例方法上使用synchronized

表示共享对象一定是this

并且同步代码块是整个方法体。

第三种:在静态方法上使用synchronized

表示找类锁。

类锁永远只有1把。

就算创建了100个对象,那类锁也只有一把。

对象锁:1个对象1把锁,100个对象100把锁。类锁:100个对象,也可能只是1把类锁。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。