java多线程学习

java多线程

线程的概念就不赘述了,有几个需要注意的点:

1.static pubic void main(String[] args)这就是程序的主线程,它也是一个线程。

2.java中有两个实现多线程的方式继承Thread方法,implements Runnable接口。

3.多线程应用中的多种功能:大致如下图(盗的图~)

先贴上一个最简单的多线程的例子:

import java.lang.Thread;

public class Main {

    static public void main(String[] arg) {
        BaseThread baseThread = new BaseThread();
        new Thread(baseThread, "A").start();
        new Thread(baseThread, "B").start();
    }
}




public class BaseThread implements Runnable{
    
    public void run(){
        for(int i=0; i<5; i++){
            System.out.println(Thread.currentThread().getName()+"  "+i);
        }
    }
}

结果:

B  0
A  0
B  1
A  1
B  2
A  2
B  3
A  3
B  4
A  4

这个大概能反应效果,但是好像有点有规律,不要在意这些细节。

线程的实现:cup是分时处理指令的,就是说在一个时钟周期内处理一条指令,那么现在我开启两个线程,cpu就会一会儿执行线程A的指令,一会儿执行线程B的指令,看起来好像是A和B同时在执行一样,其实cpu内部还是一个异步执行机制。

那么如果按照上面这种情况就会出现一个问题,我们之前在代码中苦心经营的时间上的逻辑关系在这里就会变得相当难搞了,举一个例子:

现有一个订票的网站,有A,B两个用户,现在只剩一张票,现在A买了一张票,票数减一等于零了,但是现实当前票数的代码还没有变化还是1,然后执行B,B看到还剩一张点击购买,怎么办?如何解决这种问题。有逻辑性的代码执行不同步的后果。这时就需要用到图中提供的那么多API来实现这些功能了。哦,还有就是多线程的指令执行控制,是系统决定的,不是我们所能掌握的,我们只能通过这些API去管理使用。

线程的生命周期

线程同步和死锁 举个订票的简单例子:

 1 public class BaseThread implements Runnable{
 2     
 3     public void run(){
 4         for(int i=0; i<10; i++){
 5             if(count>0){
 6                 try{
 7                     Thread.sleep(1000);
 8                 }catch(InterruptedException e){
 9                     System.out.println(e.getStackTrace());
10                 }
11                 count--;
12                 System.out.println(count);
13             }
14         }
15     }
16     
17     static public void main(String[] arg) throws InterruptedException {
18         BaseThread baseThread = new BaseThread();
19         Thread h1 = new Thread(baseThread,"h1");
20         Thread h2 = new Thread(baseThread,"h2");
21         h1.setPriority(1);
22         h2.setPriority(5);
23         h1.start();
24         h2.start();
25     }
26     private int count = 5;
27 }

测试时会有这种输出

3
3
2
1
0
-1

出现这种结果的原因:假如现在count=1,然后A线程访问了,count>1,这时B线程也访问了,count>1,然后这时这两个线程就都进入了if,然后就对count进行了--操作。所以出现了这种情况。

这时可以通过线程同步的方法解决这个问题,用synchronized  这时同步关键字,它能保证一个时间内只有一个线程访问。例如上面代码可以变成这样:

public class BaseThread implements Runnable {

	public void run() {
		for (int i = 0; i < 10; i++) {
			synchronized (this) {
				if (count > 0) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						System.out.println(e.getStackTrace());
					}
					count--;
					System.out.println(count);
				}
			}
		}
	}

	static public void main(String[] arg) throws InterruptedException {
		BaseThread baseThread = new BaseThread();
		Thread h1 = new Thread(baseThread, "h1");
		Thread h2 = new Thread(baseThread, "h2");
		h1.setPriority(1);
		h2.setPriority(5);
		h1.start();
		h2.start();
	}

	private int count = 5;
}

synchronized (对象){}然后把要同步的代码放进{}内就可以了,对象就是要屏蔽的对象,这个里面就是this。

关于synchronized我最近看到一个关于它功能的说明比较好的:

http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html(下面说明的来源)

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

 这里有一点值得注意,

还有好多东西:

多线程与单例:http://www.cnblogs.com/zxh1210603696/p/4157294.html(单例与多线程)

notify 和 wait :http://www.cnblogs.com/mengdd/archive/2013/02/20/2917956.html  (多线程通信wait和notify) http://www.cnblogs.com/gw811/archive/2012/10/17/2727266.html(依然是线程的同步synchronize)。

原文地址:https://www.cnblogs.com/chaiwentao/p/4138974.html