java核心卷之多线程核心内容学习笔记(一)

——每天寥寥的几笔,坚持下去,将会是一份沉甸甸的积累。


老实说,多线程这块学起来真不是很轻松。接下来,本人整理了下自己学习多线程这块的一些核心内容(如果细讲,恐不是一篇两篇文章所能囊括的)


1.线程的概念: 通俗的理解,进程是一个大的运行的程序,而线程就是该程序里面的一些子程序(功能)

                          专业的说,线程是CPU使用的基本单元,由线程ID,程序计数器,寄存器集合和栈组成,它与属于同一进程的其他线程共享代码段,数据段和其他资源。

从上面介绍中,要理解的核心暂时就是:共享数据。因此多个线程抢一份资源,结果就出现了线程安全,因此,线程的相关处理就很重要了。


2.无脑的使用(会使用是最低级别的,懂原理可居中层,理解底层源码实现的可居高层,自己可以按需修改源码并实现之的则乃高人也)

两种创建线程的方法,

其一:继承Thread类创建一子类,然后覆写run方法,并new出该子类的实例对象(构造函数的参数就是你要共享,或许就是一个遥控器对象),最后调用start方法。

其二:一个类实现runnable接口,实现run方法,然后用这个类的对象作为参数new出相关Thread对象,该对象就是该类的一个线程,调用start函数启动线程。


3.多线程的高性能(多个同时并发执行),但也存在缺点,就是共享数据

如何创建多线程共享一份数据,对应上面的两种方法,实例代码如下

public class Share {//作为共享数据的对象类
	private int shareNum;
	Share(int num){
		this.shareNum = num;
	}
	public synchronized int getShareNum(){//由于该对象共享,必须添加synchronized关键字避免同时操作
		return this.shareNum;
	}
}

//方法一:继承Thread类
public class Method01 extends Thread{
	private Share share;
	Method01(Share share){//构造函数传入共享数据
		this.share = share;
	}
	public void run(){

	}
}
//方法二:实现runnable接口
public class Method02 implements Runnable{
	private Share share;
	Method02(Share share){//构造函数传入共享数据
		this.share = share;
	}
	public void run(){

	}
}

public class Test{
	//方法一
	Share share = new Share(10);//建公共的共享数据对象,以下线程都已该对象为参数
	new Method01(share);//线程1,操作share
	new Method01(share);//线程2,操作share
	new Method01(share);//线程3,操作share
	new Method01(share);//线程4,操作share
	//方法二
        Runnable method02 = new Method02(share);//以公共对象share作为参数构造公共的runnable对象method02,然后以下线程都以这个共享的runnable对象为参数
        new Thread(method02);//线程1,操作method02
        new Thread(method02);//线程2,操作method02
        new Thread(method02);//线程3,操作method02
        new Thread(method02);//线程4,操作method02

   总结:其实方法二就是把方法一中的runnable接口对象给抽取出来了。
}

4.synchronized的注意点。

说这个关键字之前,大家必须清楚一个事实:java中的每一个对象都有一个内部锁。线程A要调用该对象的synchronized的方法时,必须获得该对象的锁,而一旦拿到锁,其他线程就拿不到改锁,也就不能调用该方法,也就实现了阻塞的功能。

明白上面的概念,其实使用上没啥难度:

其一:是直接加到方法返回类型前,则默认拥有了this对象的内部锁;

其二:是同步阻塞,即

<span style="font-size:14px;">synchronized(obj){}//则拥有obj对象的锁,该对象是程序员自己建出来的“虚拟锁”</span>

但是,

但是,

有一点要注意,对于第一种方法——直接加到方法返回类型前的,由于默认拥有了this对象的内部锁,因此该线程占据了该类所有带synchronized关键字前缀的方法的使用。而想避免这种情况出现,就可以选择使用多个上面提到的虚拟锁,不同的方法用第二种方法控制不同的虚拟锁。比如:

public class A{
	private Object obj1;
	private Object obj2;
	void B(){
		synchronized(obj1){
			//to-do-something
		}
	}
	void C(){
		synchronized(obj2){
			//to-do-something
		}
	}
	//这样方法B和C就不耦合了
}



线程的知识远不止这些。。。初级知识就不多写了,中级知识——有关中断,notify,notifyall,wait的下一篇文章再介绍吧。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章