java io、集合、线程、字符串、gc、jvm可谓是java中的最基本的知识,尤其是线程操作复杂,相应难懂,要想java基础知识扎实,上面提到的几个方面的知识点都要精通,这样方可以称自己掌握java方面基础知识。
总结一下java线程知识,平时接触过线程,尤其是在android开发中,线程可谓是无处不在,稍有不注意就会报错。在java中线程也是无处不在,main就是一个线程,只不过被包装好了,一般接触不到。
我的无数次的复习经历告诉我,学习知识最快,最深刻的方法就是从解题开始,不要先看概念,遇到新知识点,新概念先自己用已有的原始知识解一遍,然后再去看相关解释,会发现,概念是那么的浅显易懂。废话不多说,先上题:
1.用两个线程,交叉输出“123...56”和“abc...z”,要求输出结果为“12a34b67c...5556z”。
分析:此题用到线程同步互斥的知识点。线程1输出->唤醒线程2->线程1等待,线程2输出->唤醒线程1->线程2等待...一直到输出完毕。本题几乎可以全面考察线程互斥的知识。有了这些分析就可以上代码:
/**
*
* @author mxr
*ClassName ThreadTest
*@Version 1.0
*@ModifiedBy 2014-10-27
*@Copyright RSDSYST
*/
public class ThreadTest extends Thread {
class Thread1 implements Runnable {
private Object _lock;
public Thread1(Object lock) {
_lock = lock;
}
@Override
public void run() {
try {
synchronized (_lock) {
for (int i = 0; i < 26; i++) {
System.out.print((2 * i + 1) + "" + (2 * i + 2));
_lock.notifyAll();//唤醒其他线程
_lock.wait();//释放锁,等待
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Thread2 implements Runnable {
private Object _lock;
public Thread2(Object lock) {
_lock = lock;
}
@Override
public void run() {
synchronized (_lock) {
for (int i = 0; i < 26; i++) {
System.out.print((char) ('a' + i));
_lock.notifyAll();//叫醒其他线程
if(i<25){
try {
_lock.wait();//释放锁,等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
public static void main(String[] args){
Object lock=new Object();
Thread t1=new Thread(new ThreadTest().new Thread1(lock));
Thread t2=new Thread(new ThreadTest().new Thread2(lock));
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面的代码就是按照分析的思想去实现。上面的wait(),notifyAll()都只能用在同步代码块内。
2.用线程实现银行取钱问题,当出现错误时,如何进行同步。
/**
*
* @author mxr
*ClassName ThreadTest
*@Version 1.0
*@ModifiedBy 2014-10-27
*@Copyright RSDSYST
*/
class User{
int sumCount = 100;
User(){}
public <span style="color:#ff0000;">synchronized</span> void oper(int count){
sumCount = sumCount - count;
System.out.println(" has get: "+count+". the sumCount is: "+sumCount);
}
}
public class ThreadTest extends Thread {
User user;
int useCount;
ThreadTest(User user,int useCount){
this.user = user;
this.useCount = useCount;
}
public void run(){
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
user.oper(useCount);
}
public static void main(String[] args){
System.out.println(Thread.currentThread().getName()+" is running");
User user = new User();
ThreadTest tt = new ThreadTest(user,30);
ThreadTest tt1 = new ThreadTest(user,20);
ThreadTest tt2 = new ThreadTest(user,30);
ThreadTest tt3 = new ThreadTest(user,10);
tt.start();
tt1.start();
tt2.start();
tt3.start();
System.out.println(Thread.currentThread().getName()+" is end");
}
}
代码如上,当在oper上不加synchronized时,出现的结果是错误的,因为在同一时间访问了money,加上同步之后,一个时刻只能有一个访问,所以避免了错误。
3.简单的对线程池的理解和应用。
线程池用ExecutorService和Executors来建立,为程序提供线程,当线程很多时,可以大大的节省内存空间,线程池是一个线程队列,当队列的容量小时,多出来的线程就会排队等待。
用容量为2的线程池来实现银行取款问题:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @author mxr
*ClassName ThreadTest
*@Version 1.0
*@ModifiedBy 2014-10-27
*@Copyright RSDSYST
*/
class User{
int sumCount = 100;
User(){}
public <span style="color:#ff0000;">synchronized</span> void oper(int count){
sumCount = sumCount - count;
System.out.println(" has get: "+count+". the sumCount is: "+sumCount);
}
}
public class ThreadTest extends Thread {
User user;
int useCount;
ThreadTest(User user,int useCount){
this.user = user;
this.useCount = useCount;
}
public void run(){
try {
sleep(30);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
user.oper(useCount);
}
public static void main(String[] args){
System.out.println(Thread.currentThread().getName()+" is running");
User user = new User();
ThreadTest tt = new ThreadTest(user,30);
ThreadTest tt1 = new ThreadTest(user,20);
ThreadTest tt2 = new ThreadTest(user,30);
ThreadTest tt3 = new ThreadTest(user,10);
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.execute(tt);
pool.execute(tt1);
pool.execute(tt2);
pool.execute(tt3);
System.out.println(Thread.currentThread().getName()+" is end");
}
}
同样的,线程池自身是没有同步的,对共享块需要自己用synchronized来控制同步。
有一篇详细介绍java线程的专栏非常详细:http://lavasoft.blog.51cto.com/62575/27069/