Java基础复习-线程
创建线程的方式
继承Thread类
/*通过继承Thread类的方式创建线程
*/
//1.创建一个子类继承Thread类
class Thread1 extends Thread{
//2.重写Thread类的run()
@Override
public void run(){
for (int i = 0; i < 100; i++) {
if(i%2==0){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
}
public class ThreadTest {
public static void main(String[] args) {
//3.创建这个子类的对象
Thread1 t1=new Thread1();
//4.通过对象调用start(),该方法的作用:1.启动当前线程 2.调用当前线程的run()方法
t1.start();
}
}
实现Runnable()接口
/*通过实现Runnable接口的方式创建线程
*/
//1.创建实现Runnable方法的类
class Test implements Runnable{
//2.实现Runnable中的run()
@Override
public void run(){
for (int i = 0; i < 100; i++) {
if(i%2==0){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
}
public class RunnableTest {
public static void main(String[] args) {
//3.创建对象
Test ts = new Test();
//4.将上述对象作为参数传入Thread类的构造器中
Thread t1=new Thread(ts);
//5.调用start()
t1.start();
}
}
实现Callable()接口
/*通过实现Callable接口的方式创建线程
*/
//1.创建实现Callable方法的类
class CallTest implements Callable{
//2.重写call()
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 0; i < 100; i++) {
if(i % 2 == 0){
sum +=i;
}
}return sum;
}
}
public class CallableTest {
public static void main(String[] args) {
//3.创建实现类的对象
CallTest ct = new CallTest();
//4.将实现类的对象作为参数传入FutureTask构造器,创建FutureTask对象
FutureTask ft = new FutureTask(ct);
//5.将FutureTask对象作为参数传入Thread类的构造器中,创建Thread对象并启动线程
new Thread(ft).start();
try{
//6.get()得到的返回值即为call()中的返回值
Object sum = ft.get();
}catch(InterruptedException e){
e.printStackTrace();
}catch (ExecutionException e){
e.printStackTrace();
}
}
}
使用线程池
class Test implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i%2==0){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
}
public class PoolTest {
public static void main(String[] args) {
//1.提供指定线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//2.执行线程
service.execute(new Test());//Runnable
// service.submit(Callable callable);//Callable
//3.关闭连接池
service.shutdown();
}
}
线程的优先级
线程的优先级有10档,默认为5
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
getPriority();//该方法获取线程优先级
setPriority(Thread.MAX_PRIORITY);//该方法设置线程优先级
/*
线程的优先级高意味着它有更高的概率抢占CPU的执行权,并不意味着一定要高优先级的线程执行完低优先级的线程才能执行
*/
线程的生命周期
1.新建
2.可运行
3.运行
4.阻塞:等待阻塞,同步阻塞,其他阻塞
5.死亡
线程的同步
多线程如果共享资源,会产生安全问题,通过同步机制来解决线程的安全问题
同步代码块
使用synchronized来同步。
何为需要被同步的代码?如果一段代码操作了共享数据,它就需要被同步,其中,共享数据即为多个线程共同操作的变量。
synchronized中的锁(同步监视器)可以是任何一个类的对象,若线程通过Runnable创建,也可以用this,但是多个线程必须得共用一把锁。
Object lock = new Object();
synchronized(lock){
//需要被同步的代码
}
同步方法
如果操作共享数据的代码完整地声明在了一个方法中,就可以用这种方式,只要在方法返回类型前加synchornized就行。
Lock锁
//1.实例化
private ReentrantLock lock =new ReentrantLock();
//2.实现Runnable中的run()
@Override
public void run(){
//2.上锁
lock.lock;
try{
//需要同步的代码
}
finally {
//3.解锁
lock.unlock();
}
}
线程通信涉及的三个方法
wait()当前线程进入阻塞状态,并释放同步监视器
notify()唤醒被wait()的一个线程(按优先级)
notifyAll()唤醒所有被wait()的线程
必须使用在同步代码块或同步方法中,调用者为同步监视器