利用Callable接口实现多线程。
使用Runnable接口可以解决单继承局限,但是Runnable接口也有自己的缺点就是Runnable接口里面的run方法不能返回操作结果。
import java.util.concurrent.Callable;
class MyThread implements Callable<String>{//多线程主体类
private int ticket = 10; //卖票
@Override
public String call() throws Exception{
for(int x = 0;x < 100;x++){
if(this.ticket > 0){ //还有票可以出售
System.out.println("卖票,ticket=" + this.ticket--);
}
}
return "票已卖光!"; //返回结果
}
}
/*通过FutureTask类继承结果可以发现它是Runnable类的子类,并且FutureTask类可以接收Callable接口实例,这样依然可以利用
*Thread类来实现多线程的启动,而如果想要接收返回结果,利用Future接口中的get()方法即可。
*/
public class TestDemo{
public static viod main(String[] args) throws Exception {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
FutureTask<String> task1 = new FutureTask<String>(mt1);
FutureTask<String> task2 = new FutureTask<String>(mt2);
new Thread(task1).start();
new Thread(task2).start();
System.out.println("A线程的返回结果:" + task1.get());
System.out.println("B线程的返回结果:" + task2.get());
}
}
可能的程序执行结果: (前面输出省略。。)
卖票,ticket = 2;
卖票,ticket = 2;
卖票,ticket = 1;
卖票,ticket = 1;
A线程的返回结果:票已卖光!
B线程的返回结果:票已卖光!
进程在哪里?
当用户使用java命令执行一个类时就表示启动了一个JVM的进程,而主方法只是这个进程上的一个线程而已,而且每一个JVM进程都至少启动以下两个线程:
main线程:程序的主要执行,以及启动子线程。
gc线程:负责垃圾收集。
线程的休眠:
线程的休眠指的是让程序的执行速度变慢一些,在Thread类中线程休眠操作方法为:public static void sleep(long millis) throws InterruptedException,设置的休眠单位是毫秒(ms).
线程的优先级
在Java的线程操作中,所有的线程在运行前都会保持就绪状态,此时哪个线程的优先级高,哪个线程就有可能会先被执行。
线程的同步与死锁
多个线程操作同一资源就有可能出现不同步的问题,想要解决不同步的问题就要使用同步操作,同步操作就是一个代码块中的多个操作在同一个时间段内只能有一个线程进行,其他线程要等待此线程完成后才可以继续执行。在java中要实现线程的同步操作可以使用synchronized关键字:
1.同步代码块:利用synchronized包装的代码块,但是需要指定同步对象,一般设置为this。
2.同步方法:利用synchronized定义的方法。
同步代码块:
同步方法:
请解释多个线程访问同一资源时需要考虑到哪些情况?有可能带来哪些问题?
1.多个线程访问同一个资源时,考虑到数据操作的安全性问题,一定要使用同步操作。同步有以下两种操作模式:
(1)同步代码块:synchronized(锁定对象){代码};
(2) 同步方法:public synchronized 返回值 方法名称(){代码}