方式一:
定义一个类,继承Thread类,重写其中的run方法,
在主方法中创建你定义的这个类的对象,调用start()方法
定义的线程类:
package com.jingfei.homework;
public class Mythread extends Thread {
@Override
public void run() {
System.out.println(this.getName()+"创建的线程执行了");
}
}
主类:
package com.jingfei.homework;
public class Demo1 {
public static void main(String[] args) {
//创建线程的三种方式
Mythread mythread = new Mythread();
Mythread mythread1 = new Mythread();
mythread.setName("线程1");
mythread1.setName("线程2");
//mythread.run();//注意直接调用run方法是不能开启线程,只是调用run方法而已.
System.out.println("---------------");
mythread.start();// 必须调用start()由底层调用run方法才会开启线程.
mythread1.start();
}
}
方式二:
定义一个类,实现Runnable接口,重写run方法,
在主方法中,创建接口的子类对象,创建Thread对象,然后把接口的子类对象,作为参数传给Thread
再调用start()方法开启线程
定义的类实现Runnable接口:
package com.jingfei.homework;
public class Mythread2 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"创建的子线程执行了");
}
}
主类:
package com.jingfei.homework;
public class Demo2 {
public static void main(String[] args) {
Mythread2 mythread2 = new Mythread2();
Thread thread = new Thread(mythread2, "线程1");//可以直接传入线程名字
Thread thread1 = new Thread(mythread2);
thread1.setName("线程2");
thread.start();
thread1.start();
}
}
既然是接口,当然也可以用匿名内部类来获取子类对象
package com.jingfei.homework;
public class Demo21 {
//既然是需要一个Runnable接口,那可以用匿名内部类
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"创建的子线程执行了");
}
};
Thread thread = new Thread(r);
thread.setName("线程1");
Thread thread1 = new Thread(r);
thread1.setName("线程2");
thread.start();
thread1.start();
}
}
方式三:
这种方法可以带回线程的返回值
定义一个类实现Callable接口,重回call方法,创建一个 FutureTask<> 这个类,把Callable接口的子类对象传给他,创建Thread类 然后把FutureTask的对象传给Thread 最后开启线程,
创建一个类实现Callable接口:
package com.jingfei.homework;
import java.util.concurrent.Callable;
public class MyThread3 implements Callable {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"创建的子线程执行了");
return 100;//必须由返回值,这是这种开启线程独有的
}
}
主类:
package com.jingfei.homework;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread3 myThread3 = new MyThread3();
FutureTask ft1 = new FutureTask(myThread3);
Thread thread1 = new Thread(ft1,"线程1");
FutureTask ft2 = new FutureTask(myThread3);
Thread thread2 = new Thread(ft2,"线程2");
//thread2.setName("线程2");
thread1.start();
thread2.start();
Integer integer1 = ft1.get();
System.out.println("线程1的返回值"+integer1);
Integer integer2 = ft2.get();
System.out.println("线程2的返回值"+integer2);
}
}
既然是接口,当然也可以用匿名内部类来实现
package com.jingfei.homework;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Demo31 {
public static void main(String[] args) {
Callable callable = new Callable() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() + "创建的子线程执行了");
return 100;
}
};
FutureTask ft = new FutureTask<>(callable);
FutureTask ft1 = new FutureTask<>(callable);
//FutureTask是Java实现了Runnable的子类,可以用来封装Callable任务
Thread thread = new Thread(ft);
Thread thread1 = new Thread(ft1);
thread.setName("线程一");
thread1.setName("线程二");
thread.start();
thread1.start();
}
}
线程中的一些方法,控制线程
线程加入jion(),加入的线程优先执行,其他线程互相争抢cpu
设置守护线程setDaemon(true) ,主线程死亡后,守护线程会立即死亡
获取和设置优先级getPriority(),setPriority() [1,10],1最小,10最大,
线程休眠sleep(),让线程阻塞,但是线程并不释放当前已经拥有的资源
线程礼让yield() (不一定一人一次执行,还是争抢cpu)
中断线程interrupted() 打断线程的阻塞状态
强制停止线程 stop(),使线程死亡
线程安全的问题,得满足三个条件:
1.是否是多线程环境
2.是否还有共享数据
3.是否有多条语句在操作这个共享数据
如果出现线程安全问题,我们用同步来解决
同步代码块
synchronized (锁对象){
//包裹你可能出现数据安全问题的代码
}
同步方法
public synchronized void test(){
//包裹你可能出现数据安全问题的代码
}
锁对象:
同步代码块使用的锁对象,是任意锁对象,(不同对象要想互斥访问,必须用同一个锁对象)
同步方法使用的锁对象 是this
静态同步方法使用锁对象是 当前类的字节码文件对象 .class
我们自己手动创建线程,是比较耗费底层资源的,而且这个线程使用完之后,就死亡了,不能重复利用
JDK1.5之后,获取线程池对象,Java给我们提供了一个工厂,用这个工厂类,来来获取线程池对象
新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool ():根据任务的数量来创建线程对应的线程个数
public static ExecutorService newFixedThreadPool ( int nThreads):固定初始化几个线程
public static ExecutorService newSingleThreadExecutor ():初始化一个线程的线程池
代码示例
package com.jingfei.homework;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo4 {
public static void main(String[] args) {
ExecutorService pool1 = Executors.newCachedThreadPool();
ExecutorService pool2 = Executors.newFixedThreadPool(2);//固定2个
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "pool1中创建的子线程执行了");
}
};
Runnable runnable2 = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "pool2中创建的子线程执行了");
}
};
//向线程池pool1中提交任务,线程池根据任务的多少创建多少个子线程,直到任务全部完成,子线程就会处于等待状态,不会死亡
/*pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.submit(runnable);
pool1.shutdown();*/
//向线程池pool2中提交任务,线程池固定了只能有2个子线程,所以这两个子线程互相争抢任务执行,执行完成后,继续争抢,直到任务全部完成,子线程就会处于等待状态,不会死亡.
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.submit(runnable2);
pool2.shutdown();
}
}
谢谢!