多线程是指在同一个程序中,不同的执行路径。
线程的性能分析:
多线程的优点:
提高了cpu的利用率。在一个线程阻塞的时候或进行IO的时候,通过时间片分配,其他线程可以正常执行,这使得cpu不会被闲置,从而提高了利用率。
加快了程序响应时间。 点击一个应用程序的某个功能,该应用程序中同时跑起来的多个线程,极快的都会轮流得到执行,而不会卡在该功能某个细节处,影响整个执行大局。So ,这使得程序看起来响应较快。
多线程的缺点:
在只考虑电脑只有一个cpu的情况下。一个cpu只能在某一时刻,运行一段任务代码。但是因为操作系统的时间片分配,使得各个线程都会得到执行权<cpu控制权>。并且这个时间片非常之快,所以看起来像是所有程序都在同时运行一样。但是每次时间片切换时,必须要将cpu中的当前进程的数据指针保存,然后再加载进来下一个线程执行数据。这个过程被称作:Context-Switch也就是上下文切换。 在cpu切换线程的同时,因为上下文切换开销而造成了时间开销。
每个线程都会开辟自己的堆栈空间,用来记录自己的执行指令和程序数据。同时也会占用一些操作系统资源用来管理线程。所以线程如果过多了,那么内存空间开销也会增加。
线程的创建方式:
1.实现Runnable接口
2.继承Thread类
public class ifeve { public static void main(String[] args) { /* myThread my1 = new myThread(); myThread my2 = new myThread(); System.out.println("my1="+my1.getName()); System.out.println("my2="+my2.getName()); my1.start(); my2.start();*/ 这是第一种继承了Thread类,并在子类中写出run()方法 ----------------------------华丽分割线------------------------- Thread my1 = new Thread(new otherThread()); Thread my2 = new Thread(new otherThread()); my1.start(); my2.start(); } // 这是第二种将Runnable作为对象传入Thread中 } class myThread extends Thread{ public void run() { //必须用public 对于继承父类的方法不能缩小其范围。 此处run()不可以加参数列表 for(int i=0;i<10;i++) System.out.println(this.getName()+" this is a thread1="+i); } static void fuck() {} } class otherThread implements Runnable{ public void run() { for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName()+" that is a thread2="+i); //看来curretThread()是静态方法 } }
线程安全问题:
多线程在同时操作共享数据的时候会产生安全问题。
比如说:为了高效操作一个实现了Runnable接口的对象变量,于是创建两个线程<A,B>同时操作该变量。
add()代码如xia:
public class Counter { protected long count = 0; public void add(long value){ this.count = this.count + value; } }
如下图 : 图片出自:http://ifeve.com/race-conditions-and-critical-sections/
一段方法代码被解析成为多条cpu运行指令,cpu运行的是指令指令指令。
然后就没法确定到底最后的值是2,3,5中的那个了。
当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。存在竞态条件的代码区域被称为临界区。为了能解决这种安全问题,从上面可以看出:
多线程在遇到临界区时,必须保证在某一时刻只存在一个线程可以访问临界区,在这个线程访问临界区结束后,其他线程才能进来。这样就可以保证不会发生安全问题了。
并发之美系列博客终于要开始啦~ 这篇只是抛砖引玉,说的比较浅。
而且最近发现了一个大牛云集的网站,特别推荐给大家:并发编程网
并且发现好多经典书目的作者都是阿里系的,技术圣地!