Java中实现多线程的函数调用及优化
1. 多线程函数调用
Java中实现多线程的函数调用可以通过继承Thread类或实现Runnable接口来实现。下面我们分别来介绍一下这两种实现方式。
1.1 继承Thread类
继承Thread类是Java中比较常用的一种实现方式。我们需要重写Thread类的run方法,并在其中写入要执行的代码。下面是一个示例代码:
public class MyThread extends Thread {
public void run() {
for(int i=0; i<10; i++) {
System.out.println("MyThread running " + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
在该示例代码中,我们定义了一个MyThread类,它继承自Thread类,并且重写了run方法。在主函数中,我们创建了一个MyThread对象并调用了它的start方法,该方法会启动一个新的线程并执行run方法中的代码。当MyThread对象的run方法执行完毕后,该线程会自动结束。
1.2 实现Runnable接口
另一种实现多线程的方式是实现Runnable接口。我们也需要重写run方法,并在其中写入要执行的代码。不同的是,我们需要创建一个Thread对象,并将我们的实现类作为参数传入。下面是一个示例代码:
public class MyRunnable implements Runnable {
public void run() {
for(int i=0; i<10; i++) {
System.out.println("MyRunnable running " + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
}
}
在该示例代码中,我们定义了一个MyRunnable类,它实现了Runnable接口,并且重写了run方法。在主函数中,我们创建了一个MyRunnable对象和一个Thread对象。我们将MyRunnable对象作为参数传入Thread对象的构造函数中,并调用Thread对象的start方法。该方法会启动一个新的线程并执行我们实现类的run方法中的代码。
2. 多线程优化
在编写多线程程序时,我们需要注意一些优化的问题,下面我们来介绍一些多线程优化的方法。
2.1 使用线程池
在创建多个线程的时候,频繁的创建和销毁线程会对系统资源造成一定的开销,因此我们可以使用线程池来避免这种开销。线程池维护了一组线程,可以在需要的时候直接从线程池中获取线程来执行任务,任务执行完毕后线程不会被销毁,而是将线程归还给线程池。下面是一个示例代码:
public class MyThread implements Runnable {
public void run() {
for(int i=0; i<10; i++) {
System.out.println("MyThread running " + i);
}
}
}
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
for(int i=0; i<10; i++) {
executor.execute(new MyThread());
}
executor.shutdown();
}
}
在该示例代码中,我们创建了一个ExecutorService对象,并使用Executors工厂类创建了一个固定大小的线程池,大小为4。然后我们通过循环向线程池提交10个任务,每个任务都是一个MyThread对象。最后我们调用线程池的shutdown方法来关闭线程池。
2.2 使用同步锁
在多线程程序中,共享资源的并发访问可能会导致数据不一致或者程序出现异常。我们可以使用同步锁来避免这种情况的发生。同步锁可以保证在同一时间段内,只有一个线程可以访问共享资源,其他线程需要等待锁的释放才能访问。下面是一个示例代码:
public class Counter {
private int count;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class MyThread implements Runnable {
private Counter counter;
public MyThread(Counter counter) {
this.counter = counter;
}
public void run() {
for(int i=0; i<1000000; i++) {
counter.increment();
}
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(new MyThread(counter));
Thread t2 = new Thread(new MyThread(counter));
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
在该示例代码中,我们创建了一个Counter类,它包含一个计数器count,我们定义了两个同步方法increment和getCount来对计数器进行读写操作。在MyThread类中,我们重复对计数器进行1000000次的自增操作。在主函数中,我们创建了两个MyThread对象,并将它们分别作为参数传入两个线程中,两个线程共享一个Counter对象。最后我们在主函数中调用了两个子线程的join方法,等待两个线程执行完毕后,输出计数器的值。
3. 总结
在实现多线程程序时,我们可以通过继承Thread类或实现Runnable接口来进行函数调用。在优化多线程程序时,我们可以使用线程池来避免频繁的线程创建和销毁,使用同步锁来避免数据不一致或程序异常。在实际开发中,我们需要根据实际需求和场景来选择合适的多线程实现方式和优化方法。
