线程总结要点

Thread相关:

线程相关方法

1. java启动时至少有两个线程,一、是主线程;二、垃圾回收线程

2. 线程获取当前线程名方法:Thread.currentThread().getName();

3. 设置线程的名称:MyThread t1 = new MyThread(); t1.setName("MyThread1");

4. 设置线程的级别,MyThread t3 = new MyThread();t3.setName("MyThread3");

t3.setPriority(10);级别:1-10

5.守护线程ThreadDaemon t1 = new ThreadDaemon();

t1.setName("Thread");

t1.setDaemon(true);//守护线程

t1.start();

6.加入线程:ThreadJoin t1 = new ThreadJoin();

t1.setName("Thread");

t1.start();

t1.join();//执行该条语句的线程,会加入到t1线程后面,t1结束后采取执行自己的线程

for(int i=0;i<100;i++){

System.out.println(Thread.currentThread().getName()+"-"+i);

}

7. Thread.sleep(1000);在指定的毫秒内,线程休眠,休眠期间会放弃cpu的资源,但是不会放弃监视器的资源;

8.线程停止方法:t1.interrupt();

9.通过实现Runnable接口,从而实现线程,首先创建一个MyRunnable类实现Runnable接口,然后创建新的线程,将接口放入线程中,MyRunnable r1 = new MyRunnable();

Thread t1 = new Thread(r1,"Thread");

t1.start();

10.线程阻塞三个必要条件:1.是否是多线程环境;2.是否是共享数据;3.是否是多条语句操作共享数据;

11.买票问题:如果单纯使用如下方式:

public  class SellTicket implements Runnable {

private int tickets = 100;

public void run() {

while(tickets>0){

System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"");

}

}

}

package tm.change_06;

public class SellTicketDemo {

public static void main(String[] args) {

SellTicket r = new SellTicket();

Thread t1 = new Thread(r);

Thread t2 = new Thread(r);

Thread t3 = new Thread(r);

t1.setName("张飞");

t2.setName("关羽");

t3.setName("刘备");

t1.start();

t3.start();

t2.start();

}

}

这样很可能出现负数票和重复票的情形;

为了避免出现重复票和负数票的情形,添加synchronized进行包裹;

12. ArrayList list1 = new ArrayList();//线程不安全,是允许线程并发操作,优点是速度块

List list2 = (List) Collections.synchronizedList(list1);//线程安全的

//线程安全

StringBuffer sb = new StringBuffer();

Vector v = new Vector();

13.使用Lock方法锁住线程:

使用方式,1.声明Lock, private Lock lock=new ReentrantLock();2.加锁lock.lock();,3.解锁lock.unlock();

14.线程同步:

弊端:1.效率低,2.容易产生死锁;原因在于两个或两个以上的线程在争夺资源的时候,发生了一种互相等待的现象;

15.Object类中提供三种方法:

1.wait()等待,及时让出CPU,也让出监视器资源

2.notify()唤醒第一个线程;

3.notifyAll()唤醒所有等待的线程;

加油相关问题:

1. 创建JYZ,声明汽油的数量,建立flag来表明油够的状态truefalse的状态,创建flagget,set方法;分别创建同步的加油和减油的操作;

2. 创建Car类,实现Runnable接口,在类中声明加油站对象,并在构造函数中体现;

3. 创建Worker类,实现Runnable接口,在类中声明加油站对象,并在构造函数中体现;

JYZ类相关代码:

private Integer qycount = 0;//汽油的数量

private boolean flag = false;//false 油不够了

public boolean isFlag() {

return flag;

}

public void setFlag(boolean flag) {

this.flag = flag;

}

//向加油站中注入汽油

public synchronized void plusOil(int c){

if(this.flag){ //加油站中的油是够的,就需要等待,释放掉CPU资源和监视器

try {

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

//否则加油c

this.qycount += c;

System.out.println(Thread.currentThread().getName()+"增加了"+c+"升汽油");

//加好后设置油满了,通知所有

this.setFlag(true);

this.notifyAll();

}

//减少汽油

public synchronized void subtractOil(int c){

//因可能会有多辆车进行加油,减少可能会很多,所以在当前的汽油数量少于乘客需要加油的数量时,那么需要让线程进行等待,设置油的状态是未满,否则在循环中减少汽油的数量

while(this.qycount<c){//汽油不够

System.out.println(Thread.currentThread().getName()+""+c+"升汽油,等待中......");

this.setFlag(false);

try {

this.notifyAll();

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

this.qycount-=c;

System.out.println(Thread.currentThread().getName()+""+c+"升汽油");

}

}

Car类相关操作:

声明JYZ类,初始化一次性加油的数量,在Car的构造函数中,设置加油的数量,因为是随机使用Random函数;在run方法中,加油站的油减少

public class Car implements Runnable {

private JYZ jyz;

private Integer count=0;//一次加油的数量

public Car(JYZ j){

this.jyz = j;

Random random = new Random();

this.count = random.nextInt(10)+1;

}

@Override

public void run() {

this.jyz.subtractOil(this.count);

}

}

Worker类:

如果油没有满的情况下,jyz的油会继续增加20

public class Worker implements Runnable {

private JYZ jyz;

public Worker(JYZ j){

this.jyz = j;

}

@Override

public void run() {

while(true){

this.jyz.plusOil(20);

}

}

}

如果是所有的车一起来,创建加油站的实例对象,创建Worker实例对象,创建线程,遍历来的车,如果是新的车,这样就传入新的车,每辆车开启线程,当循环后,开启主线程

public static void main(String[] args) {

JYZ jyz = new JYZ();

Worker worker = new Worker(jyz);

Thread t1 = new Thread(worker,"工作人员");

for(int i=0;i<10;i++){

Car car = new Car(jyz);

Thread t = new Thread(car,"汽车"+i);

t.start();

}

t1.start();

}

如果要按照顺序来加油,

JYZ jyz = new JYZ();

Worker worker = new Worker(jyz);

Thread t1 = new Thread(worker,"工作人员");

t1.start();

for(int i=0;i<10;i++){

Car car = new Car(jyz);

Thread t = new Thread(car,"汽车"+i);

t.start();

t.join();

}

线程组:

1.创建MyRunnable接口实现Runable接口

2.创建主类,在main方法中创建线程组

  1)创建ThreadGroup对象,在对象中有名称;

  2)分别创建两个线程,指明名称;

  3) 设置线程组级别

  4)设置守护线程

public static void main(String[] args) {

// System.out.println(Thread.currentThread());

// Thread t1 = new Thread(new MyRunnable());

// System.out.println(t1);

method2();

}

public static void method2(){

ThreadGroup tg = new ThreadGroup("新的线程组");

Thread t1 = new Thread(tg,new MyRunnable(),"张三");

Thread t2 = new Thread(tg,new MyRunnable(),"李四");

tg.setMaxPriority(10);

tg.setDaemon(true);

System.out.println(t1);

System.out.println(t2);

}

线程池:

定义:线程池是线程的容器,使用线程时,从线程池中获得线程,线程不用时,将线程还给线程池,避免反复创建线程和结束线程;

思路:

1.创建线程池

ExecutorService pool = Executors.newFixedThreadPool(2);

2.让线程池执行任务

pool.submit(new MyRunnable());

pool.submit(new MyRunnable());

pool.submit(new MyRunnable());

3.结束线程池

pool.shutdown();/

4.结束线程池:1)组织新任务的加入;2)关闭线程池,试图停止所有正在执行的活动任务;

pool.shutdownNow();

第二种思路:

1.创建线程池

ExecutorService pool = Executors.newFixedThreadPool(2);

2.让线程池执行任务

Future<Integer> f1=pool.submit(new MyCallable(100000000));

Future<Integer> f2=pool.submit(new MyCallable(200000000));

Integer i1 = f1.get();

Integer i2 = f2.get();

System.out.println(i1);

System.out.println(i2);

3.结束线程

pool.shutdown();//阻止新任务的加入

pool.shutdownNow();//关闭线程池,并或的为执行任务列表

System.out.println("完成");

两种方法不同点:

1.Future<?> submit(Runnable task)

提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。

2.Future<T>  submit(Callable<T> task)

  提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。

线程的多种打开实现方式:

1.继承thread实现多线程:

new Thread(){

public void run(){

System.out.println("thread1");

}

}.start();

2.实现了Runnable接口来实现多线程

new Thread(new Runnable(){

@Override

public void run() {

System.out.println("thread2");

}

}).start();

3.使用多重run方法,不过结果只是thread4

new Thread(new Runnable(){

@Override

public void run() {

System.out.println("thread3");

}

}){

public void run(){

System.out.println("thread4");

}

}.start();

使用ThreadLocal来实现多线程操作,并保证同一个Connection,进行事务处理;

一、创建AppContext

1)创建单例AppContext单例对象;

2)声明ThreadLocal类对象;

3)使用ThreadLocal绑定连接,获取绑定连接,解绑连接;

代码:

public class AppContext {

// 类变量

public static AppContext instance = new AppContext();

//线程池子

private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();

private AppContext() {

}

public static AppContext getInstance() {

return instance;

}

/**

 * 绑定

 * @param conn

 */

public void bind(Integer conn){

threadLocal.set(conn);

}

/**

 * 获取绑定对象

 */

public Integer get(){

return threadLocal.get();

}

/**

 * 解除绑定

 */

public void unbind(){

threadLocal.remove();

}

}

猜你喜欢

转载自blog.csdn.net/u012994320/article/details/70476665
今日推荐