线程创建方式一:
-
继承Thread类;
-
重写run方法;
-
创建继承了Thread类的对象,调用start方法;
public class TestThread extends Thread{ public static void main(String[] args) { //创建线程对象 TestThread thread1 = new TestThread(); //启动线程 thread1.start(); for (int i = 0; i < 20; i++) { System.out.println("我好爱JAVA"+i); } } //重写run方法 @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("我爱JAVA"+i); } } }
以下截图是程序运行结果,可以看出进程不是以一行一行运行的,先运行了main方法里面的for循环,最后才输出了重写的run方法,这是因为线程在启动的过程还需要一段时间,就是thread1.start()的时候。
导入jar包
-
下载jar包,官网下载maven;
-
导入jar包到项目;
- 新建一个lib目录;
- jar包放到lib目录下;
- 添加到项目依赖;
-
使用jar包;
创建线程方式二
- 实现Runnable接口;
- 重写run方法;
- 创建Runnable接口实现类的对象;
- 启动线程,创建一个Thread类的对象,构造方法里面传Runnable接口实现类的对象。
public class TestThread3 implements Runnable{
@Override
public void run() {
System.out.println("nihao");
}
public static void main(String[] args) {
TestThread3 testThread3 = new TestThread3();
Thread thread1 = new Thread(testThread3);
thread1.start();
}
}
线程不安全
-
多个线程操作同一个资源,就会造成线程抢夺资源;
-
例如:
public class TestThread3 implements Runnable { int ticketNum = 10; @Override public void run() { while (true) { if (ticketNum <= 0) { break; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了第" + ticketNum-- + "张票"); } } public static void main(String[] args) { TestThread3 thread = new TestThread3(); new Thread(thread,"thread-0").start(); new Thread(thread,"thread-1").start(); new Thread(thread,"thread-2").start(); } }
以下截图是程序的运行结果,如图就会造成线程不安全。
如果代码里面加一个关键字synchronized(同步的),JVM会锁定调用此方法或者代码块的线程。
public class TestThread3 implements Runnable {
int ticketNum = 10;
@Override
public void run() {
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {//锁定调用此块的线程,别的线程访问不到,等到此进程结束之后,其他进程机会进来执行
if (ticketNum <= 0) {
return;
}
System.out.println(Thread.currentThread().getName() + "抢到了第" + ticketNum-- + "张票");
}
}
}
public static void main(String[]args){
TestThread3 thread=new TestThread3();
new Thread(thread,"thread-0").start();
new Thread(thread,"thread-1").start();
new Thread(thread,"thread-2").start();
}
}
创建线程方式三:
- 实现Callable接口,需要返回值类型;
- 重写call方法,需要抛出异常;
- 创建线程目标;
- 创建执行服务:ExecutorService service = Executor.newFixedThreadPool(1);
- 提交执行:Future result = service.submit(t1);
- 获取结果:boolean r1 = result.get();
- 关闭服务:service.shutdownNow();
public class Test1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable t1 = new TestCallable();
TestCallable t2 = new TestCallable();
TestCallable t3 = new TestCallable();
ExecutorService service = Executors.newFixedThreadPool(3);//3指的是同时开启三个线程
Future<Boolean> r1 = service.submit(t1);//将t1、t2、t3依次提交过去
Future<Boolean> r2 = service.submit(t2);
Future<Boolean> r3 = service.submit(t3);
boolean result1 = r1.get();//得到结果是boolean类型
boolean result2 = r2.get();
boolean result3 = r3.get();
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
service.shutdownNow();//关闭服务
}
}
class TestCallable implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
return true;//这里为了演示方便 西安让它的返回值不变,一直是true
}
}