JAVA基础(一)多线程基本功能

今天主要学习JAVA多线程相关的知识,在介绍多线程之前还是先回顾一下线程相关的基础知识:

一、基本概念

关于进程和线程:

进程是指正在运行的程序,拥有独立的内存空间和系统资源

线程是进程内的执行单元,进程内的线程共享内存空间和系统资源,多线程不能提高程序的执行速度,但能够提高应用程序的使用率 

进程与线程差异的核心在于是否共享内存空间和系统资源,且存在包含关系

关于并发和并行:

并行是指逻辑上同时发生,即某一时间内同时运行多个程序,并发指物理上同时发生,指在一个时间点同时运行多个程序


二、多线程创建方法

JAVA的多线程是通过调用C/C++底层的程序来实现的,实现方式有两种:

方式1、继承Thread父类,并重写Thread方法中的run函数

public class MyThread extends Thread {
	public void run() {
		System.out.println("这是多线程");
	}
}
public static void main(String[] args) {
  MyThread mt = new MyThread();	//直接创建线程,执行start()即可
  mt.start();
}

方式2、创建类实现Runnable接口,并将该类作为线程的传入参数
public class MyRunnable implements Runnable {
	public void run() {
		System.out.println("方式2创建线程");
	}
}
public static void main(String[] args) {
	MyRunnable mr = new MyRunnable();
	Thread t = new Thread(mr);
	t.start();
}








方式2比方式1的优势在于:1、仅实现接口,解决了多继承难题
                                            2、实现代码分离,面向对象的思想(如卖理财系统,一个runnable实现类即可实现多线程卖理财)




三、几个实用的线程方法:
3.1 基本函数
public final String getName()
获取线程名称,返回线程字符串
public final void setName(String)
设定线程名
Thread.currentThread().getName()
获取当前线程的线程名(静态函数的链式表示)

3.2 线程优先级设置
public final int getPriority()
获取当前线程优先级1-10
public final void setPriority(int )
更改当前线程优先级1-10

3.3 线程状态控制
public static void sleep(long millis)
线程休眠:以毫秒为单位暂停执行一段时间
public final void join()
线程加入,将线程设置为优先执行,join后的线程执行完后才会执行其他线程
public static void yield()
线程礼让,线程暂时让出,即瞬间礼让行为,此时仍然可能抢到资源
public final void setDaemon(Boolean on)
将线程标记为守护线程,守护线程的含义是 用于守护别人的线程,当进程只有守护线程存在时,守护线程直接死亡
public final void stop()
public final void interrupt()
中断线程,stop()让线程强制停止,已过时,现在常用interrupt(),通过跑出InterruptedException异常进行处理,可执行后续的catch代码和try代码块后的代码

3.4 线程同步控制
synchronized(Object o){}
1、同步代码块关键字,对象o作为同步锁, 需要使用相同的对象才能锁上,对象类型不限
2、可以直接放在方法前全局修饰符后直接修饰方法, 其同步方法锁对象为this,而静态方法的锁为当前类的class对象
Lock lock = new ReentrantLock()
1、JDK5的lock锁对象及其具体实现,比synchronized更明确加锁及放锁时机(synchronized也够用了)
2、解锁lock.unlock()步骤一般放在finally代码块中,确保释放锁,此时可以没有catch代码块

3.5 线程通信
虽然存在线程锁的机制保证数据的线程安全,但由于线程抢占资源是随机的,对于线性流程会造成同一步骤多次争抢资源导致浪费,所以需要线程间的通信以提高效率
以下方法与synchronized方法结合使用,通过改变使用相同锁的代码块的状态实现线程通信,这些方法均在Object类中
public void wait()
public void notify()
public void notifyall()
wait()方法表示让出自身线程的控制权,在不收到notify()指令时不再抢占系统资源
notify()方法表示自身执行完毕,通知其它线程不再进行等待(这时自身仍会抢占资源,所以需要在抢占到时执行wait()操作让出控制权)
notifyall()方法则会唤起所有该锁相关的等待线程,可以视具体情况进行使用

双线程时的流程图如下:




四、线程的生命周期:
正常的线程步骤有如下几种:
新建:创建线程对象
就绪:有执行资格,没有执行权
运行:有执行资格,有执行权
        阻塞:没有执行资格、没有执行权,可激活进入就绪态
死亡:线程对象编程垃圾,等待被回收

线程的周期如下图所示:


五、线程组与线程池:
5.1线程组相关方法:
线程组的表示类为:TreadGroup,可以自行创建线程组,并统一设置优先级或守护线程属性等
Thread类包含以下线程方法
public String getThreadGroup()
获取线程组的名称
public Thread(ThreadGroup tg, Runnable targer, String name)
将线程归类到特定组

5.2 线程池的方法:
线程池的创建,通过Excecutor工厂类执行以下静态方法
public static ExecutorService newCachedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()
上述方法只会区分线程池的线程数量差别,即无限制、设定数量、单一数量
线程池函数只能执行Runnable或Callable对象代表的线程,调用过程如下:
public <T> submit(Runnable)   //or Callable
传入接口直接开始线程
public void shutdown()
结束线程池,如果不执行shutdown函数则程序不会自动退出

5.3 关于Callable:
和Runnable的差别在于存在返回值,使用Callable属于实现多线程的第三种方法,依赖线程池而存在,需要重写执行函数如下:
public Future<T> call()
Callable可以完全采用和Runnabl相同的方式建立对象,但当需要返回值时,需要建立带参构造函数,下面举例,求1到n的数的和:
public class AddCallableExample implements Callable<Integer> {
	private int num;				//求和的值
	public AddCallableExample(int num){
		this.num = num;
	}
	public Integer call() throws Exception {
		int sum = 0;
		for(int i = 1;i<=num;i++){
			sum +=i;
		}
		return sum;					//返回总和
	}
}
这时,submit的返回值即为call函数的结果需要建立Future对象作为返回值的接收容器
public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService ec = Executors.newFixedThreadPool(2);
		Future<Integer> f = ec.submit(new AddCallableExample(100));
		System.out.println(f.get()); //返回为5050
}

5.4 定时器
首先需要建立一个Timer类来进行触发,传入TimerTask抽象类,并通过重写TimerTask的run()方法实现:
public class TaskExample extends TimerTask {

	private Timer t;	//必须传入参数t,方便后续结束Timer
	public TaskExample(Timer t){
		this.t=t;
	}
	public void run() {
		System.out.println("定时处理~~~");
		t.cancel();	//完成操作,退出t
	}
}
主要流程如下
Timer t = new Timer();
t.schedule(new TaskExample(),3000);	//只执行一次
t.schedule(new TaskExample(),3000,2000);	//执行多次,若执行多次,不能进行cancel操作














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值