多线程的概念和一些问题总结

1.进程和线程间的区别:

进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。

线程与进程的区别归纳:

a.地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

b.通信:进程间通信:管道、信号量、共享内存、消息队列(https://blog.csdn.net/zhaohong_bo/article/details/89552188 一些进程间通信的方法),线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

c.调度和切换:线程上下文切换比进程上下文切换要快得多。

d.在多线程OS中,进程不是一个可执行的实体。

2.多线程的好处以及问题:

(1)发挥多核 CPU 的优势
(2)更快的响应时间
(3)便于建模

问题:线程安全问题

3.多线程的优先级

线程优先级决定了线程能分配到的时间片的多少,也就决定了线程需要多或者少分配一些处理器资源,线程的优先级范围从1到10,在线程构建时可以通过setPriority(int)来修改优先级,默认优先级是5,设置优先级时,针对频繁阻塞(IO/休眠)的线程需要设置较高的优先级,而偏重计算(需要较多CPU时间或者偏运算)的线程则设置较低的优先级,确保处理器不会被独占。《Java并发编程的艺术》一书中,在Mac OS X10.10,jdk1.7环境下,设置优先级不起效,给出的原因是操作系统不理会java线程对于优先级的设定m,然而在Windos10,jdk 1.8环境下,亲测有效,可能是之后的版本对设置优先级进行了优化。但程序的正确性还是不要依靠线程优先级的高低比较好。下面是测试代码,有兴趣的同学可以尝试一下。

package art.ch4;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 测试线程优先级是否有效
 */
public class Priority {
    private static volatile boolean notStart = true;
    private static volatile boolean notEnd   = true;

    public static void main(String[] args) throws Exception {
        List<Job> jobs = new ArrayList<Job>();
        for (int i = 0; i < 10; i++) {
            int priority = i < 5 ? Thread.MIN_PRIORITY : Thread.MAX_PRIORITY;
            Job job = new Job(priority);
            jobs.add(job);
            Thread thread = new Thread(job, "Thread:" + i);
            thread.setPriority(priority);
            thread.start();
        }
        notStart = false;
        Thread.currentThread().setPriority(8);
        System.out.println("done.");
        TimeUnit.SECONDS.sleep(10);
        notEnd = false;

        for (Job job : jobs) {
            System.out.println("Job Priority : " + job.priority + ", Count : " + job.jobCount);
        }

    }

    static class Job implements Runnable {
        private int  priority;
        private long jobCount;

        public Job(int priority) {
            this.priority = priority;
        }

        public void run() {
            while (notStart) {
                Thread.yield();
            }
            while (notEnd) {
                Thread.yield();
                jobCount++;
            }
        }
    }
}

4.守护线程(Deamon线程)

守护线程是一种支持型线程,主要用作程序中后台调度及支持性工作,当jvm中不存在非守护线程时,jvm将会退出,可以在线程启动前将其设置为守护线程,但不能在其启动后设置为守护线程。当没有非守护线程时,守护线程会立即结束,即使守护线程中又finally代码块,所以,蹦依靠守护线程中的finally中内容来关闭资源等。

5. 多线程共用一个数据变量注意什么

在Runnable中定义了全局变量,run方法回修改变量时,如果有多个线程同时使用该线程对象,那么就会造成全局变量的值被同时修改,造成错误。

ThreadLocal时jdk引入的一种机制,它用于解决线程间共享变量,使用ThreadLocal声明的变量,即使在线程中属于全局变量,针对每个线程来说,这个变量也是独立的。

volatile变量每次被线程访问时,都强迫线程从主内存中重读改变变量的最新值,而当该变量发生修改时,也会强迫线程将最新的值刷新回主内存中。这样,不同的线程都能及时的看到该变量的最新值。

6.线程间通信方式

线程孤立地运行,价值很小,但是多个线程相互能够互相配合,相互通信,会带来很大价值。

1.volatile关键字

关键字volatile可以用来修饰变量,就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的修改必须同部刷新回共享内存,这种特性能保证一个线程的修改,对其他线程可见。

2. 同步
同步是指多个线程通过 synchronized 关键字这种方式来实现线程间的通信。主要确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,保证了线程对变量访问的可见性和排他性。

3.wait/notify 机制

一个线程A调用了对象O的wait方法进入等待状态,而另一个对象B调用了对象O的notify或者notifyAll方法,线程A收到通知后从对象O的wait方法返回,进而执行后续操作。上述两个线程通过对象O来完成交互。

线程执行wait、notify、notifyAll都必须先获得锁。

4.管道输入/输出流

管道输入输出主要用于线程之间的数据传输,而传输的媒介位内存。,主要包括4种具体的实现:pipedOutputStream,pipedInputStream,pipedRead和pipedWriter,前两种面向字节,后两种面向字符。

5.join方法

线程A种执行了B.thread()方法,A等待B线程终止之后才从thread.join()方法返回,继续执行A线程。

 

参考:

1.https://www.nowcoder.com/ta/review-java/review?tpId=31&tqId=21079&query=&asc=true&order=&page=11

2.《java并发编程的艺术》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值