您的位置:首页 > 编程语言 > Java开发

Java基础知识(2):多线程

2013-08-13 14:46 211 查看
创建线程:

Java api中,java.lang.Thread为基础线程类。线程是执行的一段程序,因此就是一个函数调用,但它可以访问父线程的资源。

共有三种创建线程的方式:

1、派生Thread的子类,实现抽象的run方法,通过调用子类对象的start()方法启动线程

class BackgroundSorter extends Thread {
List l;
public BackgroundSorter(List l) {
this.l = l;
}

public void run() {
Collections.sort(l);
}
}


调用

Integer[] a = new Integer[]{5, 4, 3};

List<Integer> list = new LinkedList<Integer>(
Arrays.asList(new Integer[]{5, 4, 3}));

Thread sorter = new BackgroundSorter(list);
sorter.start();


2、实现Runnable接口对象并传递给Thread构造函数

Thread t = new Thread(new Runnable() {
public void run() {
Collections.sort(list);
}
});

t.start();


3 还可以匿名创建线程并执行

new Thread(new Runnable() {
public void run() {
Collections.sort(list);
}
}).start();


线程的生命周期

NEW:Thread已被创建,但没有被start()执行
RUNNABLE:线程正在运行
BLOCKED:等待锁,线程阻塞
WAITING:线程调用了Object.wait()或Thread.join()而等待
TIMED_WAITING:线程调用了Thread.sleep()而等待
TERMINATED:以运行完毕

线程同步

当多个线程同时访问一个数据,并且业务操作是非原子的,需要考虑线程锁的问题,目的是控制竞争资源的合理访问。

public class Count {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

User user = new User("Tom", 400);

Thread t1 = new MyThread(user, 10);
Thread t2 = new MyThread(user, 10);
Thread t3 = new MyThread(user, 10);
Thread t4 = new MyThread(user, 10);

t1.start();
t2.start();
t3.start();
t4.start();

}

}

class User {
public String ID;
public int cash;

public User(String ID, int cash) {
this.ID = ID;
this.cash = cash;
}

public String getID() {
return ID;
}

public void setID(String iD) {
ID = iD;
}

public int getCash() {
return cash;
}

public void setCash(int cash) {
this.cash = cash;
}

public synchronized void oper(int x) {

try {
Thread.sleep(10L);

cash += x;
System.out.println("账号:" + ID + "余额:" + cash + "变化:" + x);

Thread.sleep(10L);
} catch (InterruptedException e) {
e.getStackTrace();
}
}
}

class MyThread extends Thread{

private User user;
private int change;

public MyThread(User user, int change) {
this.user = user;
this.change = change;
}

public void run() {

user.oper(change);
}
}


其中oper()为同步方法,锁对应的实例对象,因为对账户的操作必须是原子的。否则,输出的增量和实际的余额将是不合理的。

同步块

public void oper(int x) {

try {
Thread.sleep(10L);

synchronized(this) {
cash += x;
System.out.println("账号:" + ID + "余额:" + cash + "变化:" + x);

Thread.sleep(10L);
}
} catch (InterruptedException e) {
e.getStackTrace();
}
}

原理是一样的,同样是锁类的实例对象,也可以锁实例对象的成员对象。但是范围变小了。

互斥锁

互斥锁为Lock接口,实现子类有ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock

后面两个是读写锁的分离,有利于提高程序性能。

Lock lock = new ReentrantLock();

class User {
public String ID;
public int cash;

Lock lock;

public User(String ID, int cash, Lock lock) {
this.ID = ID;
this.cash = cash;
this.lock = lock;
}

public void oper(int x) {

try {
Thread.sleep(10L);

lock.lock();

cash += x;
System.out.println("账号:" + ID + "余额:" + cash + "变化:" + x);

lock.unlock();
Thread.sleep(10L);

} catch (InterruptedException e) {
e.getStackTrace();
}
}
}

一个独立的锁锁定一个类实例对象的一个操作。锁是从外部传进来的,统一管理某个操作的原子性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: