原创

Java基础语法


JAVA基础

一、循环分支

1.一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3。编程 找出1000以内的所有完数。(因子:除去这个数本身的其它约数)

/**
 * @autor LZH
 * @date 2020/11/1  12:47
 */
      for (int i = 1; i <=1000 ; i++) {
                int sum=0;
                for (int j = 1; j < i; j++) {
                    if (i%j==0){
                       sum+=j;
                }
              }if (sum==i){
                    System.out.println(i);
                }
            }

2.100以内的质数(只能被1和本身整除 如:2,3,5,7,11)

/**基础版本
 * @autor LZH
 * @date 2020/11/1  20:47
 */

  public  static void  test1(){
        boolean isFlag=true;//记录是不是质数
        for (int i = 2; i <100 ; i++) {
            for (int j = 2; j < i; j++) {
                if (i%j==0){
                    isFlag=false;//如果取模等于0,表示不是质数
                    break;//提高效率
                }
            }
            if (isFlag==true){
                System.out.println(i);
            }
            isFlag=true;//重置,进入下一个循环
        }
    }
/**高效版本
 * @autor LZH
 * @date 2020/11/1  20:55
 */
 public  static void  test2(){
        a:for (int i =2; i <100 ; i++) {//遍历1到100
            for (int j = 2; j <=Math.sqrt(i); j++) {//j:被i去除
                if (i%j==0){
                    continue a;
                }
            }
            System.out.println(i);
        }
    }

二、数组

1.循环数输出

 /**
     * @autor LZH
     * @date 2020/11/2  19:47
     * 回旋数组  如输入2  输出  1  2
     *                        4  3
     *  输入3  输出  1 2 3
     *              8 9 4
     *              7 6 5
     */
    static void test2(){
        Scanner scanner=new Scanner(System.in);
        int n = scanner.nextInt();
        int arr[][]=new int[n][n];

        int count = 0; // 要显示的数据
        int maxX = n - 1; // x轴的最大下标
        int maxY = n - 1; // Y轴的最大下标
        int minX = 0; // x轴的最小下标
        int minY = 0; // Y轴的最小下标
        while (minX <= maxX) {
            for (int x = minX; x <= maxX; x++) {
                arr[minY][x] = ++count;
            }
            minY++;
            for (int y = minY; y <= maxY; y++) {
                arr[y][maxX] = ++count;
            }
            maxX--;
            for (int x = maxX; x >= minX; x--) {
                arr[maxY][x] = ++count;
            }
            maxY--;
            for (int y = maxY; y >= minY; y--) {
                arr[y][minX] = ++count;
            }
            minX++;
        }

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                System.out.print(arr[i][j]+"\t");
            }
            System.out.println();
        }

    }

三、多线程

1.基本概念:程序、进程、线程

  • 程序**(program)**是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。

  • 进程**(process)**是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。——生命周期如:

    • 运行中的QQ,运行中的MP3播放器
    • 程序是静态的,进程是动态的
    • 进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域
  • 线程**(thread)**,进程可进一步细化为线程,是一个程序内部的一条执行路径。

    • 若一个进程同一时间并行执行多个线程,就是支持多线程的
    • 线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
    • 一个进程中的多个线程共享相同的内存单元/内存地址空间 它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全的隐患。

2.线程的创建和使用

/**
 *
 *  方式一:继承Thread类
 * 1 定义子类继承Thread类。
 * 2 子类中重写Thread类中的run方法。
 * 3 创建Thread子类对象,即创建了线程对象。
 * 4)调用线程对象start方法:启动线程,调用run方法。
 *
 * 例:遍历 1-100的偶数
 * @Autor LZH
 * @Date 2020/11/13  16:52
 */
class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            if (i%2==0){
                System.out.println(i);
            }
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        System.out.println("----lzhgy.cn----");
    }

}
/**
 * 方式二:实现Runnable接口
 * 1) 定义子类,实现Runnable接口。
 * 2) 子类中重写Runnable接口中的run方法。
 * 3) 通过Thread类含参构造器创建线程对象。
 * 4) 将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。
 * 5) 调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。
 */
class MyThread2 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            if (i%2==0){
                System.out.println(i);
            }
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        MyThread2 myThread2 = new MyThread2();
        new Thread(myThread2).start();
        System.out.println("----lzhgy.cn----");
    }

}
/**
 * 测试Thread中的常用方法:
 * 1. start():启动当前线程;调用当前线程的run()
 * 2. run(): 通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
 * 3. currentThread():静态方法,返回执行当前代码的线程
 * 4. getName():获取当前线程的名字
 * 5. setName():设置当前线程的名字
 * 6. yield():释放当前cpu的执行权
 * 7. join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才
 *           结束阻塞状态。
 * 8. stop():已过时。当执行此方法时,强制结束当前线程。
 * 9. sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前
 *                          线程是阻塞状态。
 * 10. isAlive():判断当前线程是否存活
 *
 *
 * 线程的优先级:
 * 1.
 * MAX_PRIORITY:10
 * MIN _PRIORITY:1
 * NORM_PRIORITY:5  -->默认优先级
 * 2.如何获取和设置当前线程的优先级:
 *   getPriority():获取线程的优先级
 *   setPriority(int p):设置线程的优先级
 *
 *   说明:高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下
 *   被执行。并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。
 *
 *
 * @author lzh
 * @create 2020-11-13
 */

3.线程的生命周期

4.线程的同步

/**
 * 一、解决线程安全问题的方式:
 * 1. 同步代码块:
 * synchronized (对象){
 * // 需要被同步的代码;
 * }
 *
 * 2.synchronized还可以放在方法声明中,表示整个方法为同步方法。
 * 例如:
 * public synchronized void show (String name){
 * ….
 * }
 *
 * 3.Lock锁  --- JDK5.0新增
 *
 *    synchronized 与 Lock的异同?
 *   相同:二者都可以解决线程安全问题
 *   不同:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
 *        Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())
 *
 * 二、优先使用顺序:
 * Lock -- 同步代码块(已经进入了方法体,分配了相应资源)--同步方法(在方法体之外)
 *
 * @Autor LZH
 * @Date 2020/12/1  18:03
 */
class Window implements Runnable{

    private int ticket = 100;
    //1.实例化ReentrantLock
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while(true){
            try{

                //2.调用锁定方法lock()
                lock.lock();

                if(ticket > 0){

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":售票,票号为:" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }finally {
                //3.调用解锁方法:unlock()
                lock.unlock();
            }

        }
    }
}

public class LockTest {
    public static void main(String[] args) {
        Window w = new Window();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

5.线程的通信

/**
 *  线程通信的应用:经典例题:生产者/消费者问题
 *  *
 *  * 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,
 *  * 店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员
 *  * 会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品
 *  * 了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
 *  *
 *  * 分析:
 *  * 1. 是否是多线程问题?是,生产者线程,消费者线程
 *  * 2. 是否有共享数据?是,店员(或产品)
 *  * 3. 如何解决线程的安全问题?同步机制,有三种方法
 *  * 4. 是否涉及线程的通信?是
 * @Autor LZH
 * @Date 2020/12/1  19:03
 */
public class ProductTest {

    public static void main(String[] args) {
        Clerk clerk=new Clerk();

        Producer p=new Producer(clerk);
        Thread p1=new Thread(p);
        p1.setName("生产者1");

        Consumer c=new Consumer(clerk);
        Thread c1=new Thread(c);
        Thread c2=new Thread(c);
        c1.setName("消费者1");
        c2.setName("消费者2");

        p1.start();
        c1.start();
        c2.start();
    }
}
class Clerk{
    private  static int productCount=0;
    //生产产品
    public synchronized void produceProduct() {
        if (productCount<20){
            ++productCount;
            System.out.println(Thread.currentThread().getName()+":开始生产第"+productCount+"个产品");
            notify();//唤醒消费者
        }else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void consumeProduct() {
        if (productCount>0){
            System.out.println(Thread.currentThread().getName()+":开始消费第"+productCount+"个产品");
            productCount--;
            notify();
        }else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
//生产者
class Producer implements Runnable{

    private Clerk clerk;

    public Producer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始生产..");
        while (true){
            clerk.produceProduct();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Consumer implements Runnable{

    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始消费");

        while (true){
            clerk.consumeProduct();
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

6.JDK5.0新增线程创建方式

/**
 * 创建线程的方式三:实现Callable接口。 --- JDK 5.0新增
 *
 *
 * 如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
 * 1. call()可以有返回值的。
 * 2. call()可以抛出异常,被外面的操作捕获,获取异常的信息
 * 3. Callable是支持泛型的
 *
 * @author lzh
 * @create 2020-12-2 
 */
//1.创建一个实现Callable的实现类
class NumThread implements Callable{
    //2.实现call方法,将此线程需要执行的操作声明在call()中
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if(i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}


public class ThreadNew {
    public static void main(String[] args) {
        //3.创建Callable接口实现类的对象
        NumThread numThread = new NumThread();
        //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
        FutureTask futureTask = new FutureTask(numThread);
        //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        new Thread(futureTask).start();

        try {
            //6.获取Callable中call方法的返回值
            //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
            Object sum = futureTask.get();
            System.out.println("总和为:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

/**
 * 创建线程的方式四:使用线程池
 *
 * 好处:
 * 1.提高响应速度(减少了创建新线程的时间)
 * 2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
 * 3.便于线程管理
 *      corePoolSize:核心池的大小
 *      maximumPoolSize:最大线程数
 *      keepAliveTime:线程没有任务时最多保持多长时间后会终止
 *
 * @author lzh
 * @create 2020-12-2 
 */

class NumberThread implements Runnable{

    @Override
    public void run() {
        for(int i = 0;i <= 100;i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

class NumberThread1 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 ThreadPool {

    public static void main(String[] args) {
        //1. 提供指定线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        //设置线程池的属性
//        System.out.println(service.getClass());
//        service1.setCorePoolSize(15);
//        service1.setKeepAliveTime();


        //2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
        service.execute(new NumberThread());//适合适用于Runnable
        service.execute(new NumberThread1());//适合适用于Runnable

//        service.submit(Callable callable);//适合使用于Callable
        //3.关闭连接池
        service.shutdown();
    }

}

四、

java
  • 作者:刘智豪(联系作者)
  • 发表时间:2020-02-25
  • 版权声明:自由转载-非商用-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码
  • 评论