Java学习

Posted andyalgorithm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习相关的知识,希望对你有一定的参考价值。

Java在设计之初就已经考虑到了线程的问题,因此Java可以有多种方式调用线程。

1.通过继承线程类的方式调用线程。通过对函数public void run(){……}进行覆盖来实现相关的程序

2.通过调用接口Runnable来调用线程。首先定义一个类,在类中定义一个函数为public void run(){……}用于存放相关程序。

3.通过Lambda表达式的匿名类来开启新的线程。

具体代码如下:

 1 package helloWorld;
 2 
 3 class AndyThread1 extends Thread {
 4     public void run()
 5     {
 6         for(int i=0;i<20;i++)
 7         {
 8             System.out.print(i+" ");
 9             try
10             {
11             Thread.sleep(1000);
12             }catch(Exception e)
13             {
14                 e.printStackTrace();
15             }
16         }
17         System.out.println();
18     }
19 
20 }
21 
22 class AndyThread2 implements Runnable
23 {
24     public void run()
25     {
26         for(int i=20;i<30;i++)
27         {
28             System.out.print(i+" ");
29             try
30             {
31                 Thread.sleep(1000);
32             }catch(Exception e)
33             {
34                 e.printStackTrace();
35             }
36         }
37         System.out.println();
38     }
39 }
 1                 AndyThread1 at1=new AndyThread1();
 2         AndyThread2 at2=new AndyThread2();
 3         Thread thread=new Thread(at2);
 4         new Thread(()->{
 5             for(int i=-10;i<0;i++)
 6             {
 7                 System.out.print(i+" ");
 8                 try{
 9                     Thread.sleep(1000);
10                 }catch(Exception e)
11                 {
12                     e.printStackTrace();
13                 }
14                 }
15             System.out.println();
16             }).start();
17             at1.start();
18             thread.start();
19 显示结果为:
20 0 -10 20 1 -9 21 2 22 -8 -7 23 3 -6 4 24 25 -5 5 6 -4 26 27 -3 7 28 -2 8 -1 29 9 10 11 12 13 14 15 16 17 18 19 (结果不唯一,但形式一致)

 

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

 

线程的状态有:start、join、yield、run、notify

线程具有优先级,分别为MIN_PRIORITY(1)、NORMAL_PRIORITY(5)、MAX_PRIORITY(10)

线程中存在守护线程,可以利用函数setDeamon()将某个线程设置为守护线程。主线程退出后守护线程会自动中断,否则守护线程会一直存在。

 

线程的调用过程有时会出现不同步的情况。因此,对于需要数据必须同步的情况,如生产消费者情况,则可以调用Java中锁的概念,也称为monitor。下面对其进行简述。

锁的概念是Java为了解决多个线程处理数据不同步的情况下提出来的,使用关键字为synchronize。可以在语句段前使用synchronize(this)或者synchronized(other)来声明。如果整个函数都需要同步,那么在函数前可以直接使用synchronized。在多个线程中,只有获得锁的线程才可以执行程序,否则就需要等待。用户也可以设置线程的解锁,可以使用wait()函数,在释放锁前利用notify()或者notifyAll()函数来通知其他线程可以获取锁了,其他线程的wait()函数自动解除。线程中还有比较常用的函数,如获取线程状态的函数getState()和getName()、getClass(),分别表示线程的状态、获取线程的名字、获取线程所在的类名。

以下是生产者消费者代码。在一个数组中指定数组长度为length,随机产生的数字个数不能超过此数组长度范围,逐个取出的数字也不能超过此数组的范围。

 1 class ProductorConsumer extends Thread
 2 {
 3     private static int[] arr; 
 4     private static int index;
 5     public ProductorConsumer()
 6     {
 7         index=0;
 8         ProductorConsumer.arr=new int[5];//默认数组长度为5
 9     }
10     public ProductorConsumer(int length)
11     {
12         index=0;
13         ProductorConsumer.arr=new int[length];
14     }
15     public ProductorConsumer(int[] arr)
16     {
17         index=arr.length-1;
18         ProductorConsumer.arr=new int[arr.length];//自定义数组
19         ProductorConsumer.arr=arr;        
20     }
21     
22     synchronized public void productor() throws InterruptedException
23     {
24         if(index<arr.length)
25         {
26             arr[index]=(int) (10*Math.random());
27             System.out.printf("productor: arr[%d] = %d\n",index,arr[index]);
28             index++;
29             this.notifyAll();
30         }
31         else
32         {
33             System.out.println("productor: wait");
34             this.wait();                
35         }
36     }
37     
38     synchronized public void consumer() throws InterruptedException
39     {
40         if(index>=0)
41         {
42             index--;
43             System.out.printf("consumer: arr[%d] = %d\n",index,arr[index]);
44             this.notifyAll();
45         }
46         else
47         {
48             System.out.println("consumer: wait");
49             this.wait();
50         }
51     }
52 }
        ProductorConsumer pc;
        for (int i = 0; i < 10; i++) {
            pc = new ProductorConsumer();
            pc.start();
            try {
                pc.productor();
                pc.consumer();
            } catch (InterruptedException ite) {
                ite.printStackTrace();
            }
        }
结果为:
productor: arr[0] = 6
consumer: arr[0] = 6
productor: arr[0] = 5
consumer: arr[0] = 5
productor: arr[0] = 8
consumer: arr[0] = 8
productor: arr[0] = 3
consumer: arr[0] = 3
productor: arr[0] = 8
consumer: arr[0] = 8
productor: arr[0] = 1
consumer: arr[0] = 1
productor: arr[0] = 7
consumer: arr[0] = 7
productor: arr[0] = 4
consumer: arr[0] = 4
productor: arr[0] = 7
consumer: arr[0] = 7
productor: arr[0] = 7
consumer: arr[0] = 7

 

在Java.util.包中有一个类名为java.util.concurrent.atomic.AtomicInteger,可以很安全的解决多线程同时访问造成的安全问题。直译名为原子整数,即此整数不会同时被两个线程访问。

 1 class AtomicInte {
 2     static AtomicInteger ai = new AtomicInteger(0);
 3     static int n;
 4     static int num;
 5 
 6     public AtomicInte() {
 7         AtomicInte.n = 0;
 8         AtomicInte.num = 100;
 9     }
10 
11     public AtomicInte(int n, int num) {
12         AtomicInte.n = n;
13         AtomicInte.num = num;
14     }
15 
16     public void test() throws InterruptedException {
17         Thread[] thread = new Thread[num];
18         for (int i = 0; i < num; i++) {
19             thread[i] = new Thread() {
20                 public void run() {
21                     n++;
22                     ai.getAndIncrement();
23                 }
24             };
25         }
26         for (int i = 0; i < num; i++) {
27             thread[i].start();
28             Thread.sleep(1);//不加sleep会出错,即同时开启多个线程,中间没有间断,导致有些线程并未开启
29         }
30     }
31 
32     public void print() {
33         System.out.println(n + " " + ai);
34     }
35 }
1         AtomicInte ai = new AtomicInte();
2         try {
3             ai.test();
4         } catch (InterruptedException ite) {
5             ite.printStackTrace();
6         }
7         ai.print();

 

Java.util.concurrent包中还有一些方便的类用于防止多线程同时操作所产生的错误。如CopyOnWriteArrayList、CopyOnWriteSet,适于很少写入而读取很频繁的对象;ConcurrentHashMap中的putlfAbsent()、remove()、replace();ArrayBlockingQueue等

以下为ArrayBlockingQueue的实例:

 1 class Productor extends Thread
 2 {
 3     BlockingQueue<Integer> queue;
 4     public Productor(){}
 5     public Productor(BlockingQueue<Integer> queue)
 6     {
 7         this.queue=queue;
 8     }
 9     
10     public void run()
11     {
12         int temp=0;
13         try
14         {
15             for(int i=0;i<10;i++)
16             {
17                 temp=(int)(20*Math.random());
18                 queue.put(temp);
19                 Thread.sleep(10);
20                 System.out.println("Productor: "+temp);
21             }
22         }catch(InterruptedException ite)
23         {
24             ite.printStackTrace();
25         }
26     }
27 }
28 
29 class Customer extends Thread
30 {
31     BlockingQueue<Integer> queue;
32     public Customer(){}
33     public Customer(BlockingQueue<Integer> queue)
34     {
35         this.queue=queue;
36     }
37     
38     public void run()
39     {
40         try
41         {
42             for(int i=0;i<10;i++)
43             {
44                 Integer integer=queue.take();
45                 System.out.println("Consumer: "+integer);
46             }
47         }catch(InterruptedException ite)
48         {
49             ite.printStackTrace();
50         }
51     }
52 }
1         BlockingQueue<Integer> queue=new ArrayBlockingQueue<Integer>(3);
2         new Thread(new Productor(queue)).start();
3         new Thread(new Customer(queue)).start();;

 

线程池相关的类:ExecutorService接口、ThreadPoolExecutor类、Executor类

线程池的创建可以用ExecutorService pool=executors.newCachedThreadPool();

具体可见示例:

 1 class ThreadPool implements Runnable
 2 {
 3     int state;
 4     public ThreadPool() {
 5         state = 0;
 6     }
 7 
 8     public ThreadPool(int state) {
 9         this.state = state;
10     }
11 
12     public void run() {
13         for (int i = 0; i < 5; i++)
14             if (state == 0)
15                 System.out.println("Good morning, Andy");
16             else if (state == 1)
17                 System.out.println("Good afternoon, Andy");
18             else if (state == 2)
19                 System.out.println("Good evening, Andy");
20             else if (state == 3)
21                 System.out.println("Good night, Andy");
22             else
23                 System.out.println("Good bye, Andy");
24     }
25 }

 

 1         ExecutorService pool=Executors.newCachedThreadPool();
 2         ThreadPool tp1=new ThreadPool(0);
 3         ThreadPool tp2=new ThreadPool(1);
 4         ThreadPool tp3=new ThreadPool(2);
 5         ThreadPool tp4=new ThreadPool(3);
 6         ThreadPool tp5=new ThreadPool(4);
 7         pool.execute(tp1);
 8         pool.execute(tp2);
 9         pool.execute(tp3);
10         pool.execute(tp4);
11         pool.execute(tp5);
12 结果为:
13 Good morning, Andy
14 Good morning, Andy
15 Good morning, Andy
16 Good afternoon, Andy
17 Good afternoon, Andy
18 Good afternoon, Andy
19 Good afternoon, Andy
20 Good afternoon, Andy
21 Good bye, Andy
22 Good bye, Andy
23 Good bye, Andy
24 Good evening, Andy
25 Good evening, Andy
26 Good evening, Andy
27 Good evening, Andy
28 Good evening, Andy
29 Good morning, Andy
30 Good morning, Andy
31 Good night, Andy
32 Good night, Andy
33 Good night, Andy
34 Good night, Andy
35 Good night, Andy
36 Good bye, Andy
37 Good bye, Andy

 

Java中为了使多线程操作更加安全,除了隐式锁外还有显式锁。显式锁在java.util.concurrent.locks中,含有Lock接口、ReentrantLock类:lock()、tryLock()、unlock();含有ReadWriteLock接口、ReentrantReadWriteLock类:writeLock().lock()、readLock().lock()

 

以上是关于Java学习的主要内容,如果未能解决你的问题,请参考以下文章

IOS开发-OC学习-常用功能代码片段整理

python 机器学习有用的代码片段

java代码在片段活动中不起作用

java 代码片段【JAVA】

# Java 常用代码片段

# Java 常用代码片段