Java的多线程有两种方式:
- 继承自java.lang.Thread类,线程的操作通过重载run()方法实现。
- 因为java的单继承属性,当类需要扩展其他类,可以实现runnable接口。同样runnable接口也是重载run()方法实现具体的操作。实际上Thread函数也是实现的runnable接口。
Java的多线程一般有三种实现方法:
1.继承Thread类
class ExtendTread extends Thread {
private int cnt = 10;
public void run() {
while (cnt >= 0)
System.out.println("" + cnt--);
}
}
public class ThreadTest {
public static void main(String arg[]) {
ExtendTread et = new ExtendTread();
et.start();
}
}
2.实现runnable接口,并将实现的接口和Thread相关联。使用这种方法创建线程有三个步骤:
a. 创建Runnable对象。
b. 创建Thread对象。
c. 将两者进行关联。
Runnable对象和Thread对象通过Thread的构造函数进行关联。Thread主要的构造函数有:
public Thread();
public Thread(String threadName);
public Thread(Runnable target);
public Thread(Runnable target, String name);
其中的第三个和第四个构造函数都可以进行Runnable对象和Thread对象的关联。看代码:
class ImplThread extends Object implements Runnable {
private int cnt = 10;
public void run() {
while (cnt >= 0)
System.out.println("" + cnt--);
}
}
public class ThreadTest {
public static void main(String arg[]) {
ImplThread it = new ImplThread();
Thread t = new Thread(it);
t.start();
}
}
3.第三种方法其实就是第二种方法,只是使用匿名类
public class ThreadTest {
public static void main(String arg[]) {
Thread t = new Thread(new Runnable() {
private int cnt = 10;
@Override
public void run() {
while (cnt >= 0)
System.out.println("" + cnt--);
}
});
t.start();
}
}
线程的同步
讲到线程,不可规避的一个问题就是线程的同步。很经典的一个问题:卖火车票。如果有多个线程在卖火车票,如果当只有最后一张火车票时,如果多个线程同时访问到该火车票,可能会同时售出,这样就会售出超过总数张票。在Java中主要有两种方式实现进程的同步机制。
1. 同步块/临界区
2. 同步方法
同步块/临界区就是定义一块代码片段,每次只有允许某一个线程访问。(和C++的EnterCriticalSection/LeaveCriticalSection类似)使用该方法实现Salesman问题如下代码:
class Salesman implements Runnable {
private int ticket = 10;
public void run() {
while (true) {
synchronized ("") {
if (ticket > 0)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ticket rest : " + ticket--);
}
}
}
}
}
public class ThreadTest {
public static void main(String arg[]) {
Salesman salesman = new Salesman(); // 线程关联同一个Runnable
Thread t1 = new Thread(salesman);
Thread t2 = new Thread(salesman);
Thread t3 = new Thread(salesman);
Thread t4 = new Thread(salesman);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
同步方法就是使用synchornic关键字修饰的方法,如果一个同步方法被调用了,那么同一个对象中的其他同步方法必须等待该方法执行完毕之后才能执行。
class Salesman implements Runnable {
private int ticket = 10;
synchronized private void saleATicket() {
if (ticket > 0)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ticket rest : " + ticket--);
}
}
public void run() {
while (true) {
saleATicket();
}
}
}
public class ThreadTest {
public static void main(String arg[]) {
Salesman salesman = new Salesman(); // 线程关联同一个Runnable
Thread t1 = new Thread(salesman);
Thread t2 = new Thread(salesman);
Thread t3 = new Thread(salesman);
Thread t4 = new Thread(salesman);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
此外,线程还有join,中断,礼让,优先级等动作和属性。有时间再补充。