方式一:继承Thread类
步骤:
1.自定义一个类并继承Thread类
2.自定义类需要重写Thread的run()方法
3.创建对象
4.启动线程
class MyThread extends Thread{
public void run() {
for(int i=0;i<100;i++){
System.out.println(getName()+":"+i);
};
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
mt1.start();
mt2.start();
}
}
run()和start()
run()方法:仅仅是封装了被线程执行的代码,如果直接调用就相当于普通方法调用,没有多线程效果。
start()方法:首先启动线程,然后再由JVM去调用该线程的run方法。
方式二:实现Runnable接口方式实现多线程
步骤:
1.自定义一个类并实现Runnable接口
2.重写run()方法
3.创建自定义类对象
4.创建Thread对象,将上面的自定义类的对象作为构造参数传递
class NewThread implements Runnable {
private int tickets = 100;
private Object obj=new Object();
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().
getName() + ":" + (tickets--));
}
}
}
}
}
public class RunnableDemo {
public static void main(String[] args) {
NewThread nt = new NewThread();
Thread t1 = new Thread(nt, "huge");
Thread t2 = new Thread(nt, "allen");
t1.start();
t2.start();
}
}
上面的程序中用了同步代码块来解决线程安全问题。
同步的前提:多个线程使用同一个锁对象。
当线程很多时,每个线程都会去判断同步上的锁,这样就会耗费资源,降低了程序的运行效率。
也可以用同步方法来实现,同步方法用synchronized关键字修饰方法。同步方法的锁对象是this,静态同步方法的锁对象是类的字节码文件对象(xxx.class)。
方式三:利用线程池和Callable接口实现多线程(用到了泛型,以Integer为例)
步骤:
1.创建一个线程池对象,控制要创建几个线程对象
2.添加Callable对象代表的线程,注意有返回值
(也可以是Runnable对象,但是没有返回值)
3.通过get()方法获取对象
4.执行相应操作
5.结束
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyCallable implements Callable<Integer> {
private int number;
public MyCallable(int number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int x = 1; x <= number; x++) {
sum += x;
}
return sum;
}
}
public class CallableDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
// 可以执行Runnable对象或者Callable对象代表的线程
Future<Integer> f1 = pool.submit(new MyCallable(100));
Future<Integer> f2 = pool.submit(new MyCallable(200));
// V get()
Integer i1 = f1.get();
Integer i2 = f2.get();
System.out.println(i1);
System.out.println(i2);
// 结束
pool.shutdown();
}
}