线程是CPU独立调度的基本单位,进程是资源分配的基本单位
两种创建线程的方法:
- 继承
Thread
类- 更加适用于: 没有共享资源,各自线程使用自己的属性的情况
public class Test3 {
public static void main(String[] args) {
// 创建四个线程 ,并且启动线程
Window window = new Window("窗口一");
Window window2 = new Window("窗口二");
Window window3 = new Window("窗口三");
Window window4 = new Window("窗口四");
window.start();
window2.start();
window3.start();
window4.start();
}
}
class Window extends Thread{
int tickt = 20;
public Window(String name) {
super(name);// 给线程起名字
}
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
tickt--;
System.out.println(Thread.currentThread().getName()+"买了"+i+"张票"+"还剩"+(tickt)+"张");
}
}
}
- 实现
Runnable
接口- 更加适用于,拥有共享资源的情况
public class Test4 {
public static void main(String[] args) {
// 叫做Runnable是夏磊对象
Ticket ticket = new Ticket();
// 创建线程对象
Thread t = new Thread(ticket, "线程一");
Thread t2 = new Thread(ticket,"线程二");
Thread t3 = new Thread(ticket,"线程三");
Thread t4 = new Thread(ticket,"线程四");
// 四个线程共享了一个ticke他空间
t.start();
t2.start();
t3.start();
t4.start();
// 常用格式
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("i"+i);
}
}
}).start();
}
}
class Ticket implements Runnable{
int tickt= 100;
@Override
public void run() {
while(tickt>0){
tickt--;
System.out.println(Thread.currentThread().getName()+"卖了"+(100-tickt)+"张票"+"还有"+tickt+"张");
}
}
}
- 实现
Callable
接口
1. 更加适用于有返回值的情况
public class Test5 {
public static void main(String[] args) throws Exception {
// 1.先创建实现类的对象
MyCallable callable = new MyCallable();
//2. 将callable对象装载到任务重
FutureTask<Integer> task = new FutureTask<>(callable);
//3. 创建线程对象
Thread thread = new Thread(task);
//4. 启动线程
thread.start();
// 线程启动以后, 就会计算结果, 计算 就可以获取返回结果
//Integer integer = callable.call();// 仅仅是以方法调用的方式来实现的
//System.out.println(integer);
// 子线程执行完毕以后给返回的结果
Integer integer = task.get();
System.out.println(integer);
}
}
class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 10000; i++) {
sum+=i;
}
Thread.sleep(2000);
return sum;
}
}
小总结
三种创建线程的方式总结:
- Thread
- 自定义类继承Trhead
- 重写run方法
- 创建子线程对象
- 用start方法启动
使用: 没有共享资源,各自线程使用自己的属性的情况 四个窗口各紫卖自己的20张票
- Runnable
- 实现类实现Runnable
- 重写run方法
- 创建实现类对象, 任务
- 创建Thread对象, 并且将实现类对象作为参数传入Thread构造方法中
- start 启动线程
适用于:
- 拥有共享资源.
- 如果操作比较简单 只想创建一个子线程对象的时候, 可以考虑使用线程匿名内部类的形式
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("i"+i);
}
}
}).start();
- 实现Callable
- 定义实现类 实现Callable<线程返回值类型>
- 重写 call()
- 创建实现类对象, 但是他不是一个任务
- 创建FutrueTask<线程返回值类型> 将线程实现类作为参数传入到FutrueTask的构造方法中
- 创建线程Thread对象, 并且将FutrueTask对象作为参数传入构造方法
- 启动线程start()
适用于: 想要得到线程结果的情况
Thread
的启动方式
通常线程的启动都是通过
new Thread(...).start()
方法来实现的
但我们在创建线程的时候都会重写run()
方法,这两个方法的区别是啥呢?
区别如下:
start() 可以申请一个新的栈,可以启动子线程
run() 只是一个简单的方法调用
对于多个已经开启的线程而言,每一个线程都会有自己独立的栈:
new Thread(new Myrunable()).start
new Thread(new Myrunable()).start
Thread类的常用方法
从上面这张图上面可以看到,Thread
类的方法是非常多的,下面把一些常用的方法拿出来做一些分析:
join()
方法,使用这个方法,可以完成现成的插队
操作,可以实现不同线程间的有序执行
public static void main(String[] args) throws InterruptedException {
System.out.println("start...");
//使用join来实现,先执行Thread2,再执行Thread1,再执行main线程
Thread1 thread1 = new Thread1();
thread1.start();
thread1.join();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
static class Thread1 extends Thread{
@Override
public void run() {
Thread2 thread2 = new Thread2();
try {
thread2.start();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + " Thread1 : "+i);
}
}
}
static class Thread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + " Thread2 : "+i);
}
}
}
其他的方法也可以从其他文章了解:
线程的生命周期
实现卖票的同步
public static void main(String[] args) {
MyRunnable my = new MyRunnable();
for (int i = 0; i < 4; i++) {
new Thread(my,"我是 : "+i+" 号").start();
}
}
static class MyRunnable implements Runnable{
Integer tickets = new Integer(100);
@Override
public void run() {
while (true){
synchronized (this){
if (tickets > 0){
tickets--;
System.out.println(Thread.currentThread().getName()+" 抢到了第 "+tickets.intValue()+"张票");
}else {
break;
}
}
}
}
}
lock
的基本用法
static int tickets = 100;
static Lock lock = new ReentrantLock();
static Runnable run = () -> {
while (true){
lock.lock();
try {
if (tickets > 0){
tickets--;
System.out.println(Thread.currentThread().getName()+ " 得到 "+tickets);
}else {
break;
}
} finally {
lock.unlock();
}
}
};
public static void main(String[] args) {
new Thread(run).start();
new Thread(run).start();
}
专门使用
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/202481.html