在Java中,线程由Thread类表示,用户创建线程的唯一方式是创建Thread类的一个实例,每一个线程都和这样的实例关联。在相应的Thread实例上调用start()方法来启动一个线程。
内存模型:
操作系统有自己的内存模型,C/C++这些语言直接使用的就是操作系统的内存模型,而Java为了屏蔽各个系统的差异,定义了自己的统一内存模型。
简单来说,Java开发者不再关心每个CPU核心有自己的内存,然后共享内存。而是把关注点转移到:每个线程都有自己的工作内存所有线程共享主内存。
Thread类中的start()和run()方法有什么区别
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当调用run()方法的时候,只会在原来的线程中调用,没有新的线程启动。start()方法才会启动新线程。
实际上,start()方法的作用是通知"线程规划器"该线程已经准备就绪,以便让系统安排一个时间来调用其run()方法,也就是使线程得到运行。
Thread类中的start()方法其中调用了native方法start0(),改方法的调用关系:
-------->jvm.cpp
-------->thread.cpp
-------->os_linux.cpp
-------->pthread_create
在os_linux.cpp中有这样的一个方法,*java_start(Thread *thread):
static void *java_start(Thread *thread) {
// Try to randomize the cache line index of hot stack frames.
// This helps when threads of the same stack traces evict each other's
// cache lines. The threads can be either from the same JVM instance, or
// from different JVM instances. The benefit is especially true for
// processors with hyperthreading technology.
static int counter = 0;
int pid = os::current_process_id();
...
// call one more level start routine
thread->run();
return 0;
}
点击run方法,会进入thread.cpp中的JavaThread::run()方法,里面的实现方法为
thread_main_inner();
三种使用线程的方法:
实现Runnable和Callable接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过Thread来调用。可以理解为任务是通过线程驱动从而执行的
需要实现接口中的run()方法
public class MyRunnable implements Runnable {
@Override
public void run() {
// ...
}
}
使用Runnable实例再创建一个Thread实例,然后调用Thread实例的start()方法来启动线程。
public static void main(String[] args) {
MyRunnable instance = new MyRunnable();
Thread thread = new Thread(instance);
thread.start();
}
与Runnable相比,它有返回值,并且返回值通过FutureTask进行封装
需要实现接口中的call()方法
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;//会抛出异常
}
public class MyCallable implements Callable<Integer> {
public Integer call() {
return 123;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable mc = new MyCallable();
FutureTask<Integer> ft = new FutureTask<>(mc);
Thread thread = new Thread(ft);
thread.start();
System.out.println(ft.get());
}
为什么Thread()中可以传进ft? 因为 1.public class FutureTask implements RunnableFuture 2.public interface RunnableFuture extends Runnable, Future 参数类型是接口,调用方法传递的参数可以是这接口中的任何一个实现类对象(面向接口编程)
同样也是需要实现run()方法,因为Thread类也实现了Runnable接口。
当调用start()方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的run()方法
public class ThreadDemo01 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//获取当前正在执行的线程的名称
//Thread.currentThread() - 返回当前正在运行的线程的引用
String name=Thread.currentThread().getName();
System.out.println(name+"->"+i);
}
}
}
class TestThreadDemo01{
public static void main(String[] args) {
Thread t1=new ThreadDemo01();
Thread t2=new ThreadDemo01();
t1.setName("线程one");
t2.setName("线程two");
//设置线程的优先级别1~10
//数字越大,优先级越高
//并不是优先级越高,就一定会优先执行,只是尽可能提高先执行的概率
t1.setPriority(Thread.MIN_PRIORITY);//最小值为1
t2.setPriority(Thread.MAX_PRIORITY);//最大值为10
//当两个线程都调用了run方法而不是start的时候,这时候就是在mian线程中调用,不会启动新的线程,结果就是main线程的输出
// t1.run();
//
// t2.run();
t1.start();
t2.start();
//处于main线程里面
System.out.println("--stop---");
}
}
实现接口会更好一些,因为:
package tech.aistar.day16.dead;
/**
* 本类功能:死锁
*
* @author cxylk
* @date 2020/8/14 18:01
*/
public class DeadLockDemo {
//静态域更加容易出现死锁 - 死锁 -争抢的是"临界资源"
//不加static 是不会出现死锁的,因为产生死锁就是去抢同一种资源
//而static能够保证当前对象只有一份
public static Object oo1=new Object();
public static Object oo2=new Object();
public static void main(String[] args) {
Thread t1=new T1();
Thread t2=new T2();
t1.start();
t2.start();
}
}
class T1 extends Thread{
private DeadLockDemo lock=new DeadLockDemo();
@Override
public void run() {
synchronized (lock.oo1){
System.out.println("=====1=====");
//是为了让第二个线程有足够的时间去争抢oo2(T2中的oo2)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock.oo2){
System.out.println("======2=====");
}
}
}
}
class T2 extends Thread{
private DeadLockDemo lock=new DeadLockDemo();
@Override
public void run() {
synchronized (lock.oo2){
System.out.println("=====3=====");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock.oo1){
System.out.println("======4======");
}
}
}
}
wait和notify必须放在synchronized中,不然会抛出java.lang.IllegalMonitorStateException异常
package tech.aistar.day16.advice;
/**
* 本类功能:synchronized实现 生产者和消费者 (线程之间的通信)
*
* 不共享代码,但是希望共享资源
*
* @author cxylk
* @date 2020/8/14 14:19
*/
public class AdviceDemo01 {
public static void main(String[] args) {
Box box=new Box();
Thread t1=new Product(box);
Thread t2=new Customer(box);
t1.setName("p");
t2.setName("c");
t1.start();
t2.start();
}
}
//临界资源
class Box{
private int content;//临界资源
//核心的代码
public boolean flag;//默认是false。如果box中有i[设置了值],flag=true,没有生产东西,flag=false
//线程通信的方法wait以及notify或者notifyAll方法的使用一定是出现在线程同步代码块中
//生产者调用的
public synchronized void setContent(int content) {
if(flag){//flat=true,盘中有东西,就不要继续生成,自己会叫醒消费者的线程
//然后自己进入阻塞状态
try {
wait();//当前线程就会进入到阻塞状态,必须是通过其他线程调用notify或者notifyALL
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//flag=false,生产的东西全部被消费了
//生产者要正常生产
flag=true;
this.content=content;
//通知消费者来消费
notify();//随机唤醒等待队列上的阻塞线程,1个
}
public synchronized int getContent() {
if(flag==false){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//当消费完毕
flag=false;
//唤醒一下生产者线程
notify();
//返回消费的数量
return content;
}
}
//生产者线程
class Product extends Thread{
private Box box;
public Product(Box box) {
this.box = box;
}
private int i;
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+"->"+(++i));
box.setContent(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者线程
class Customer extends Thread {
private Box box;
public Customer(Box box) {
this.box = box;
}
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+"->"+box.getContent());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package tech.aistar.day16.numletter;
/**
* 本类功能:
*
* 本类用来演示: 练习 - a1b2c3...
* 俩个线程,一个负责输出小写,一个负责输出数字,但是要求是依次循环打印.
*
* @author cxylk
* @date 2020/8/14 14:44
*/
public class NumLetter {
private boolean flag;//初值为false
public synchronized void printLetter(){
for (char i = 'a'; i <= 'z'; i++) {
if(flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
notify();
}
}
public synchronized void printNumber(){
for (int i = 1; i <=26 ; i++) {
if(flag==false){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=false;
notify();
}
}
public static void main(String[] args) {
NumLetter n=new NumLetter();
// Thread t1=new Thread(new Runnable() {
// @Override
// public void run() {
// n.printLetter();
// }
// });
Thread t1=new Thread(()->{
n.printLetter();
});
// Thread t2=new Thread(new Runnable() {
// @Override
// public void run() {
// n.printNumber();
// }
// });
Thread t2=new Thread(()->{
n.printNumber();
});
t1.start();
t2.start();
}
}
package tech.aistar.day16.numletter;
/**
* 本类功能:a12b34c56d78
*
* @author cxylk
* @date 2020/8/14 20:26
*/
public class NumLetter02 {
private boolean flag;
public synchronized void printLetter(){
for (char i = 'a'; i <='z' ; i++) {
if(flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//刚进来,flag为false,执行下面
System.out.print(i);
try {
Thread.sleep(1000);//睡1s,cpu去执行第二个线程,然后接着回来执行
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
notify();//唤醒下面阻塞的线程
}
}
public synchronized void printNumber(){
for (int i = 1; i <=26 ; i+=2) {
if(flag==false){//第一次进来走这
try {
wait();//睡眠
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i+""+(i+1));//两个数字连着打印
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=false;
notify();
}
}
public static void main(String[] args) {
NumLetter02 n=new NumLetter02();
Thread t1=new Thread(()->{
n.printLetter();
});
Thread t2=new Thread(()->{
n.printNumber();
});
t1.start();
t2.start();
}
}
package tech.aistar.day16.locks;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 本类功能:Lock重新做
* abcABC123abcABC123abcABC123 - 三个线程依次执行
*
* @author cxylk
* @date 2020/8/14 20:58
*/
public class LockDemo02 {
private Lock lock=new ReentrantLock();
//有三个线程,创建三个队列
//特点 - 很方便进行选择性通知某个等待队列的线程
//abc
private Condition c1=lock.newCondition();
//ABC
private Condition c2=lock.newCondition();
//123
private Condition c3=lock.newCondition();
//定义一个变量
private int count=0;
//打印小写字母
public void printLower(){
lock.lock();//手动申请锁
//lock.lock();//手动申请锁,将这句话放到循环外面提高性能
try {
//代码放到try里面
while (true) {
if (count != 0) {
//等待
c1.await();
}
System.out.print("abc");
Thread.sleep(500);
//打印完后加1
count = 1;
//唤醒c2这个等待队列上的线程
c2.signal();
}
} catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();//手动释放锁
}
}
//打印大写字母
public void printUpper(){
lock.lock();//手动申请锁
//lock.lock();//手动申请锁,将这句话放到循环外面提高性能
try {
//代码放到try里面
while (true) {
if (count != 1) {
//等待
c2.await();
}
System.out.print("ABC");
Thread.sleep(500);
//打印完后加1
count = 2;
//唤醒c3这个等待队列上的线程
c3.signal();
}
} catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();//手动释放锁
}
}
//打印数字
public void printNum(){
lock.lock();//手动申请锁
//lock.lock();//手动申请锁,将这句话放到循环外面提高性能
try {
//代码放到try里面
while (true) {
if (count != 2) {
//等待
c3.await();
}
System.out.print("123");
Thread.sleep(500);
count = 0;
//唤醒c1这个等待队列上的线程
c1.signal();
}
} catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();//手动释放锁
}
}
public static void main(String[] args) {
LockDemo02 demo=new LockDemo02();
//分别创建三个线程
Thread t1=new Thread(()->{
demo.printLower();
});
Thread t2=new Thread(()->{
demo.printUpper();
});
Thread t3=new Thread(()->{
demo.printNum();
});
t1.start();
t2.start();
t3.start();
}
}
顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。
1.Java 5+中的Executor接口(位于java.util.concurrent包下)定义一个执行线程的工具。它的子类型即线程池接口是
ExecutorService.
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
2.要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,因此在工具类Executors(java.util.concurrent包下)里面提供了一些静态工厂方法,生成了一些常用的线程池(这四个线程池返回的是一个new ThreadPoolExecutor对象,而ThreadPoolExecutor又是继承于AbstractExecutorService抽象类,AbstractExecutorService又实现了ExecutorService接口,ExecutorService接口又继承了Executor接口)
例:return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
public class ThreadPoolExecutor extends AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService
public interface ExecutorService extends Executor
public interface Executor
如下所示
package tech.aistar.day16.pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 本类功能:
* 可缓存线程池,先查看池中有没有以前建立的线程
* 如果有,就直接使用.如果没有,就建一个新的线程加入池中,
* 缓存型池子通常用于执行一些生存期很短的异步型任务
*
* @author cxylk
* @date 2020/8/15 20:55
*/
public class CacheThreadPoolDemo {
public static void main(String[] args) {
//创建一个可缓存池
ExecutorService executor= Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
//会在应用程序中创建大量的线程对象 - 堆里面 - 占系统资源
// new Thread(()->{
// System.out.println(Thread.currentThread().getName());
// }).start();
//提交任务
executor.submit(()->{
System.out.println(Thread.currentThread().getName());
});
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
//关闭线程池
executor.shutdown();
}
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
public class ThreadPoolExecutor extends AbstractExecutorService;
public abstract class AbstractExecutorService implements ExecutorService;
public interface ExecutorService extends Executor
package tech.aistar.day16.pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 本类功能:创建一个**可重用**固定个数的线程池,以共享的无界队列方式来运行这些线程
*
* @author cxylk
* @date 2020/8/15 21:57
*/
public class FixedThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executorService= Executors.newFixedThreadPool(3);//参数代表池中的线程数
for (int i = 0; i < 3; i++) {
//提交任务
executorService.submit(()->{
System.out.println(Thread.currentThread().getName());
});
}
executorService.shutdown();
}
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
public class ThreadPoolExecutor extends AbstractExecutorService;
public abstract class AbstractExecutorService implements ExecutorService;
public interface ExecutorService extends Executor
为什么与前面不一样?ScheduledExecutorService executorService= Executors.newScheduledThreadPool(2);
new ScheduledThreadPoolExecutor(corePoolSize)->public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor implements ScheduledExecutorService
public class ThreadPoolExecutor extends AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService
public interface ExecutorService extends Executor
public interface ScheduledExecutorService extends ExecutorService
public interface ExecutorService extends Executor
package tech.aistar.day16.pool;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* 本类功能:创建一个定长线程池,支持定时及周期性任务执行
*
* @author cxylk
* @date 2020/8/15 22:32
*/
public class ScheduledThreadDemo {
public static void main(String[] args) {
ScheduledExecutorService executorService= Executors.newScheduledThreadPool(2);
}
}
//command:要执行的任务,initialDelay:延迟首次执行的时间,period:两次执行之间的时间间隔
//unit:initialDelay和period参数的时间单位
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService(可终结的委托执行任务)
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
//super:->
static class DelegatedExecutorService extends AbstractExecutorService {
...
//委托执行员任务
DelegatedExecutorService(ExecutorService executor) { e = executor; }
...
}
package tech.aistar.day16.pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 本类功能:创建一个单线程化的线程池
* 它只会用唯一的工作线程来执行任务,保证所有的任务
* 按照指定顺序(FIFO,LIFO,优先级)执行
*
* @author cxylk
* @date 2020/8/15 20:51
*/
public class SingleThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executorService= Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
executorService.submit(()->{
System.out.println(Thread.currentThread().getName());
});
}
executorService.shutdown();
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。