java进阶-进程,线程

进程是一个应用程序。线程是进程中的一个执行场景,进程可以启用多个线程。
当运行一个javaclass时:jvm就是一个进程,jvm启动一个主线程执行main()方法,再启动一个垃圾回收线程负责看护,回收垃圾

分析程序中有几个线程:除了垃圾回收外有:(1个线程)
public class ThreadTest01{
public static void main(String[] args)
{
  m1();
}
private static void m1()
{
  m2(); 
}
private static void m2()
{
  m3();
}
private static void m3()
{
}

}

java实现线程的两种方式:
1.编写一个类直接继承java.lang.Thread,重写run方法

public class Threadtest extends {
public static void main(String[] args)
{  //创建线程
   MyThread mythread=new MyThread();
   //启动线程   ***Thread.run()为什么不行,此时没有开辟新的栈空间,相当于在主栈,也就是一个单线程,一个线程等另一个线程结束再开始
   myThread.start();//开辟一个新的栈空间,启动成功的线程会自动调用run方法,并且run方法在分支栈的底部,main方法在主栈的底部
  
}
}
public MyThread extends Thread{
public void run()
{
for(int i=0;i<1000;i++)
{
System.out.println("分支线程"+i);
}
}
}

2.编写一个类,实现java.lang.Runnable接口,实现run方法。

public class ThreadTest{
 MyRunnable r=new MyRunnable();
 Thread t=new Thread(r);//合并代码: Thread t=new Thread(new MyRunnable());
 t.start();
}
class MyRunnable implements Runnable{
public void run()
{

}
}

建议第二种方式,因为一个类继承了接口,还可以继承其他的类,而继承类是单继承的。
第三种方式:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;;
public class ThreadTest {
	public static void main(String[] args) throws InterruptedException, ExecutionException
	{//创建一个未来任务对象
	FutureTask task=new FutureTask(new Callable() {

		@Override
		public Object call() throws Exception 
		{
			// TODO Auto-generated method stub
			System.out.println("call method begin");
			Thread.sleep(1000*10);
			System.out.println("call method over");
			return null;
		}

	});
	Thread t=new Thread(task);
	t.start();
	task.get();
	//main()这里的程序想要执行,需要等待get()方法;
}
}

线程的生命周期:
在这里插入图片描述

线程的方法:

1.sleep()//当前线程进入休眠,静态方法
2.interrupt()//唤醒一个正在睡眠的线程,依靠java的异常处理机制,sleep()会因为抛异常而结束。
3.stop()//一个强行终止一个进程,容易丢失数据。

合理终止一个线程的执行:

在run方法里定义一个bool变量,true:线程运行,false:线程终止,在主进程里通过改变这个标志来控制线程的执行和终止。

线程调度的方法:
实例方法:

void setPriority(int num)
int getPriority()
最低优先级是1
默认优先级是5
最高优先级是10

静态方法:

static void yied();//让位方法,让当前进程从运行态回到就绪态。

实例方法:join()方法

t.join();// 当前线程进入阻塞,直到t线程执行结束,当前线程才能继续执行

多线程并发环境下线程的安全问题:

when?并发的环境下有共享数据,并且这个数据还会被修改

解决办法:

1.线程排队机制,线程同步,牺牲一定效率
(1)异步编程模型:t1,t2各自执行各自的synchronized(谁的共享对象){},共享代码块越小,效率越高。synchronized出现在实例方法上锁的一定是this.不灵活.局部变量没有线程安全问题;(栈区);成员变量可能会有线程安全问题:静态变量(方法区),实例化变量(堆区)

       synchoized可以修饰代码块,可以修饰函数,可以修饰类

(2)同步编程模型:线程t1必须等待线程t2执行完成。

wait和notify 不是线程对象的方法,是java中任何一个java对象都有的方法,因为这两个方法是object 类自带的。
Object o=new Object();
//wait()方法的作用,让正在o对象上活动的线程进入等待状态,并且释放o对象的锁,无期限等待,直到被唤醒为止,
o.wait();
//让正在o对象上等待的线程唤醒
o.notify();
//wait(),notify()建立在synchronized方法基础上
wait()、notify()实现生产者和消费者代码:

import java.awt.List;
import java.util.ArrayList;

public class thredtest02 {
public static void main(String[] args) throws InterruptedException
{
	//wait和notify 不是线程对象的方法,是java中任何一个java对象都有的方法,因为这两个方法是object 类自带的。
	Object o=new Object();
	//wait()方法的作用,让正在o对象上活动的线程进入等待状态,并且释放o对象的锁,无期限等待,直到被唤醒为止,
	o.wait();
	//让正在o对象上等待的线程唤醒
	o.notify();	
	//wait(),notify()建立在synchronized方法基础上
	List list=new ArrayList();
	
	Thread t1=new Thread(new Producer(list));
	Thread t2=new Thread(new Consumer(list));
	t1.start();
	t2.start();
	
}
}

class Producer implements Runnable{
    private List list;
    public Producer(List list)
    {
    	this.list=list;
    }
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true)
		{synchronized (list)
			{
			if(list.size()>0)
			{
				list.wait();
			}
			}
		Object obj=new Object ();
		list.add(obj);
		//唤醒消费者消费
		list.notify();				
		}
		
	}
	
}
class Consumer implements Runnable{
	private List list;
    public Consumer(List list)
    {
    	this.list=list;
    }
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true)
		{synchronized (list)
			{
			if(list.size()==0)
			{
				list.wait();
			}
			Object obj=list.remove(0);
			//唤醒生产者生产
			list.notify();
			}
		}
	}
	
}

守护线程的概念:等待所有线程都结束后,自动结束。垃圾回收机制就是一个典型的守护线程。
使用方法:daemonThread.setDaemon(true);

新学了线程池嘿嘿:
用线程池比用线程的实现方式要快:
频繁创建线程,频繁切换都要消耗资源。而线程池的优势是:

public TheadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory ,RejectedExceptionHandle handle)

int corePoolSize:核心线程数
int maximumPoolSize:非核心线程数
long keepAliveTime:时间
TimeUnit unit:时间单位
BlockingQueue workQueue:队列
ThreadFactory threadFactory :线程工厂
RejectedExceptionHandle handle:拒绝策略

在这里插入图片描述
java自带的线程池:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadpool {
public static void main(String[] args)
{//三种线程池,线程池参数不一样
//最快 int corePoolSize:0 int maximumPoolSize:10 long keepAliveTime:0 LinkedBlockingQueue
//先交给队列,然后创建非核心线程,线程复用,一个线程执行完任务后,接着回来执行下一个任务(会让cpu达到100%)
	ExecutorService executorService1=Executors.newCachedThreadPool();
//第二	int corePoolSize:10 int maximumPoolSize:10 long keepAliveTime:0(内存溢出)
//10个核心线程,0个非核心线程,从第11个任务开始,放在队列里,当主线程执行完10个,从队列取出10个再接着执行。
	ExecutorService executorService2=Executors.newFixedThreadPool(10, null);
//第三	int corePoolSize:1 int maximumPoolSize:1 long keepAliveTime:0
//1个核心线程,0个非核心线程,从第2个任务开始,放在队列里,当主线程执行完1个,从队列取出1个再接着执行。(内存溢出)
	ExecutorService executorService3=Executors.newSingleThreadExecutor();
	for(int i=1;i<100;i++)
	{
		executorService1.execute(new Mytask(i));
	}
	
}
}
class Mytask implements Runnable
{int i=0;
	public Mytask(int i)
	{
		this.i=i;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
	try {
		Thread.sleep(1000);
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}
		
	}
}

会存在OOM问题,建议自定义线程池参数。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值