有以下几种方法
如何创建多线程?
public static void main(String[] args){
MyThread my = new MyThread();
my.start();
for(int i=0;i<5;i++){
System.out.println("b"+i);
}
}
public class MyThread extends Thread{
@Override
public void run(){
//新的执行路径-线程,触发方式不是直接调用run,而是通过thread对象的start()方法来调用
for(int i=0;i<5;i++){
System.out.println("a"+i);
}
}
}
a和b并发执行,每次输出结果都不一样。
执行流程:
public class MyRunnable implements Runnable{
@Override
public void run(){
for(int i=0;i<5;i++){
System.out.println("a"+i);
}
}
}
public static void main(String[] args){
//1. 创建任务对象Runnable
MyRunnable r = new MyRunnable();
//2. 创建线程thread并为其分配任务r
Thread t = new Thread(r);
//3. 执行线程
t.start();
for(int i=0;i<5;i++){
System.out.println("b"+i);
}
}
与继承Thread相比有优势:
new Thread(){
@Override
public void run(){
for(int i=0;i<5;i++){
System.out.println("a"+i);
}
}
}.start();
守护用户线程的线程。
t1.setDaemon(true);
new Thread(new MyRunnable(),"name").start();
设置线程名称.
Thread.currentThread().getName());
获取当前执行线程的名称
ENUM Thread.State
Thread.sleep(millis:1000);
比如要读用户输入,线程会等着,耗时操作,等待用户输入完成。
线程是一个独立的执行路径,他的生命周期因其自身决定。否则外部中断可能导致资源没有释放,一直占用。
线程可以打中断标记,它自己会看,如果有就会触发一个异常InterruptedException
,try catch来由程序员来决定是否关闭
t1.interrupt();
给线程t1添加中断标记。
添加标记之后进入catch块,发现中断标记:
多个线程同时运行时会发生线程不安全的问题。
解决方法:
while(true){
synchronized (o) {
if (count > 0) {
System.out.println("卖票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "剩余:" + count);
} else {
break;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
让卖票成功返回true,否则返回false。
public synchronized boolean sale(){
if(count>0){
//卖票
//trycatch sleep1000ms
count--;
}else break;
}
private Lock l = new ReentrantLock();//显式锁
@Override
public void run(){
while(true){
l.lock();
if(count>0){
//卖票
//trycatch让线程sleep1000ms
count--;
}else break;
l.unlock();//对count改变之后释放锁对象
先来先得。
互相等待对方释放资源,占用自己所持资源。
api:
确保生产者在生产时消费者没有在消费。
功能接口,可以用作lambda表达式或方法引用的赋值目标。主线程可以拿到一个结果。
使用:编写实现Callable接口,实现call方法。
public static void main(String[] args){
Callable<Integer> c = new MyCallable();
FutureTask<Integer> task = new FutureTask<>(c);
new Thread(task).start();
task.get();//要抛出异常
//然后执行主线程剩下的代码
}
class MyCallable implements Callable<T>{
@Override
public Integer call() throws Exception{
Thread.sleep(3000);
return 100;
}
}
线程与任务执行流程:
newCachedThreadPool();
ExecutorService service = Executors.newCachedThreadPool();
//指挥线程池执行任务
service.execute(new Runnable(){
@Override...}
newFixedThreadPool(len);
newSingleThreadExecutor()
ScheduledExecutorService service = Executors.newScheduledThreadPool(size);
//任务 时长 时长的单位(TimeUnit的常量)
service.schedule(new Runnable(){
...
}
}, delay:5, period:1, TimeUnit.SECONDS);//5s后执行
1.8版本引入,属于函数式编程思想,让实现接口的写法更简单
Thread t = new Thread(()->System.out.println(""));
()内就是要传入的参数,(参数)->(方法体);